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 "lldb/lldb-python.h"
11 
12 #include <string>
13 #include <vector>
14 
15 #include <getopt.h>
16 #include <stdlib.h>
17 
18 #include "CommandObjectScript.h"
19 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
20 
21 #include "../Commands/CommandObjectApropos.h"
22 #include "../Commands/CommandObjectArgs.h"
23 #include "../Commands/CommandObjectBreakpoint.h"
24 #include "../Commands/CommandObjectDisassemble.h"
25 #include "../Commands/CommandObjectExpression.h"
26 #include "../Commands/CommandObjectFrame.h"
27 #include "../Commands/CommandObjectHelp.h"
28 #include "../Commands/CommandObjectLog.h"
29 #include "../Commands/CommandObjectMemory.h"
30 #include "../Commands/CommandObjectPlatform.h"
31 #include "../Commands/CommandObjectPlugin.h"
32 #include "../Commands/CommandObjectProcess.h"
33 #include "../Commands/CommandObjectQuit.h"
34 #include "../Commands/CommandObjectRegister.h"
35 #include "../Commands/CommandObjectSettings.h"
36 #include "../Commands/CommandObjectSource.h"
37 #include "../Commands/CommandObjectCommands.h"
38 #include "../Commands/CommandObjectSyntax.h"
39 #include "../Commands/CommandObjectTarget.h"
40 #include "../Commands/CommandObjectThread.h"
41 #include "../Commands/CommandObjectType.h"
42 #include "../Commands/CommandObjectVersion.h"
43 #include "../Commands/CommandObjectWatchpoint.h"
44 
45 #include "lldb/Core/Debugger.h"
46 #include "lldb/Core/InputReader.h"
47 #include "lldb/Core/Log.h"
48 #include "lldb/Core/Stream.h"
49 #include "lldb/Core/Timer.h"
50 
51 #include "lldb/Host/Host.h"
52 
53 #include "lldb/Interpreter/Args.h"
54 #include "lldb/Interpreter/CommandReturnObject.h"
55 #include "lldb/Interpreter/CommandInterpreter.h"
56 #include "lldb/Interpreter/Options.h"
57 #include "lldb/Interpreter/ScriptInterpreterNone.h"
58 #include "lldb/Interpreter/ScriptInterpreterPython.h"
59 
60 
61 #include "lldb/Target/Process.h"
62 #include "lldb/Target/Thread.h"
63 #include "lldb/Target/TargetList.h"
64 
65 #include "lldb/Utility/CleanUp.h"
66 
67 using namespace lldb;
68 using namespace lldb_private;
69 
70 
71 static PropertyDefinition
72 g_properties[] =
73 {
74     { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, NULL, NULL, "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." },
75     { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, NULL, NULL, "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." },
76     { NULL                  , OptionValue::eTypeInvalid, true, 0    , NULL, NULL, NULL }
77 };
78 
79 enum
80 {
81     ePropertyExpandRegexAliases = 0,
82     ePropertyPromptOnQuit = 1
83 };
84 
85 ConstString &
86 CommandInterpreter::GetStaticBroadcasterClass ()
87 {
88     static ConstString class_name ("lldb.commandInterpreter");
89     return class_name;
90 }
91 
92 CommandInterpreter::CommandInterpreter
93 (
94     Debugger &debugger,
95     ScriptLanguage script_language,
96     bool synchronous_execution
97 ) :
98     Broadcaster (&debugger, "lldb.command-interpreter"),
99     Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
100     m_debugger (debugger),
101     m_synchronous_execution (synchronous_execution),
102     m_skip_lldbinit_files (false),
103     m_skip_app_init_files (false),
104     m_script_interpreter_ap (),
105     m_comment_char ('#'),
106     m_repeat_char ('!'),
107     m_batch_command_mode (false),
108     m_truncation_warning(eNoTruncation),
109     m_command_source_depth (0)
110 {
111     debugger.SetScriptLanguage (script_language);
112     SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
113     SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
114     SetEventName (eBroadcastBitQuitCommandReceived, "quit");
115     CheckInWithManager ();
116     m_collection_sp->Initialize (g_properties);
117 }
118 
119 bool
120 CommandInterpreter::GetExpandRegexAliases () const
121 {
122     const uint32_t idx = ePropertyExpandRegexAliases;
123     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
124 }
125 
126 bool
127 CommandInterpreter::GetPromptOnQuit () const
128 {
129     const uint32_t idx = ePropertyPromptOnQuit;
130     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
131 }
132 
133 void
134 CommandInterpreter::Initialize ()
135 {
136     Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
137 
138     CommandReturnObject result;
139 
140     LoadCommandDictionary ();
141 
142     // Set up some initial aliases.
143     CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
144     if (cmd_obj_sp)
145     {
146         AddAlias ("q", cmd_obj_sp);
147         AddAlias ("exit", cmd_obj_sp);
148     }
149 
150     cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
151     if (cmd_obj_sp)
152     {
153         AddAlias ("attach", cmd_obj_sp);
154     }
155 
156     cmd_obj_sp = GetCommandSPExact ("process detach",false);
157     if (cmd_obj_sp)
158     {
159         AddAlias ("detach", cmd_obj_sp);
160     }
161 
162     cmd_obj_sp = GetCommandSPExact ("process continue", false);
163     if (cmd_obj_sp)
164     {
165         AddAlias ("c", cmd_obj_sp);
166         AddAlias ("continue", cmd_obj_sp);
167     }
168 
169     cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
170     if (cmd_obj_sp)
171         AddAlias ("b", cmd_obj_sp);
172 
173     cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
174     if (cmd_obj_sp)
175         AddAlias ("tbreak", cmd_obj_sp);
176 
177     cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
178     if (cmd_obj_sp)
179     {
180         AddAlias ("stepi", cmd_obj_sp);
181         AddAlias ("si", cmd_obj_sp);
182     }
183 
184     cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false);
185     if (cmd_obj_sp)
186     {
187         AddAlias ("nexti", cmd_obj_sp);
188         AddAlias ("ni", cmd_obj_sp);
189     }
190 
191     cmd_obj_sp = GetCommandSPExact ("thread step-in", false);
192     if (cmd_obj_sp)
193     {
194         AddAlias ("s", cmd_obj_sp);
195         AddAlias ("step", cmd_obj_sp);
196     }
197 
198     cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
199     if (cmd_obj_sp)
200     {
201         AddAlias ("n", cmd_obj_sp);
202         AddAlias ("next", cmd_obj_sp);
203     }
204 
205     cmd_obj_sp = GetCommandSPExact ("thread step-out", false);
206     if (cmd_obj_sp)
207     {
208         AddAlias ("finish", cmd_obj_sp);
209     }
210 
211     cmd_obj_sp = GetCommandSPExact ("frame select", false);
212     if (cmd_obj_sp)
213     {
214         AddAlias ("f", cmd_obj_sp);
215     }
216 
217     cmd_obj_sp = GetCommandSPExact ("thread select", false);
218     if (cmd_obj_sp)
219     {
220         AddAlias ("t", cmd_obj_sp);
221     }
222 
223     cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
224     if (cmd_obj_sp)
225     {
226         AddAlias ("l", cmd_obj_sp);
227         AddAlias ("list", cmd_obj_sp);
228     }
229 
230     cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
231     if (cmd_obj_sp)
232     {
233         AddAlias ("env", cmd_obj_sp);
234     }
235 
236     cmd_obj_sp = GetCommandSPExact ("memory read", false);
237     if (cmd_obj_sp)
238         AddAlias ("x", cmd_obj_sp);
239 
240     cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
241     if (cmd_obj_sp)
242         AddAlias ("up", cmd_obj_sp);
243 
244     cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
245     if (cmd_obj_sp)
246         AddAlias ("down", cmd_obj_sp);
247 
248     cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
249     if (cmd_obj_sp)
250         AddAlias ("display", cmd_obj_sp);
251 
252     cmd_obj_sp = GetCommandSPExact ("disassemble", false);
253     if (cmd_obj_sp)
254         AddAlias ("dis", cmd_obj_sp);
255 
256     cmd_obj_sp = GetCommandSPExact ("disassemble", false);
257     if (cmd_obj_sp)
258         AddAlias ("di", cmd_obj_sp);
259 
260 
261 
262     cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
263     if (cmd_obj_sp)
264         AddAlias ("undisplay", cmd_obj_sp);
265 
266     cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
267     if (cmd_obj_sp)
268         AddAlias ("bt", cmd_obj_sp);
269 
270     cmd_obj_sp = GetCommandSPExact ("target create", false);
271     if (cmd_obj_sp)
272         AddAlias ("file", cmd_obj_sp);
273 
274     cmd_obj_sp = GetCommandSPExact ("target modules", false);
275     if (cmd_obj_sp)
276         AddAlias ("image", cmd_obj_sp);
277 
278 
279     OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
280 
281     cmd_obj_sp = GetCommandSPExact ("expression", false);
282     if (cmd_obj_sp)
283     {
284         AddAlias ("expr", cmd_obj_sp);
285 
286         ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
287         AddAlias ("p", cmd_obj_sp);
288         AddAlias ("print", cmd_obj_sp);
289         AddAlias ("call", cmd_obj_sp);
290         AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp);
291         AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp);
292         AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp);
293 
294         alias_arguments_vector_sp.reset (new OptionArgVector);
295         ProcessAliasOptionsArgs (cmd_obj_sp, "-O --", alias_arguments_vector_sp);
296         AddAlias ("po", cmd_obj_sp);
297         AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
298     }
299 
300     cmd_obj_sp = GetCommandSPExact ("process kill", false);
301     if (cmd_obj_sp)
302     {
303         AddAlias ("kill", cmd_obj_sp);
304     }
305 
306     cmd_obj_sp = GetCommandSPExact ("process launch", false);
307     if (cmd_obj_sp)
308     {
309         alias_arguments_vector_sp.reset (new OptionArgVector);
310 #if defined (__arm__)
311         ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
312 #else
313         ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=/bin/bash --", alias_arguments_vector_sp);
314 #endif
315         AddAlias ("r", cmd_obj_sp);
316         AddAlias ("run", cmd_obj_sp);
317         AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp);
318         AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp);
319     }
320 
321     cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
322     if (cmd_obj_sp)
323     {
324         AddAlias ("add-dsym", cmd_obj_sp);
325     }
326 
327     cmd_obj_sp = GetCommandSPExact ("breakpoint set", false);
328     if (cmd_obj_sp)
329     {
330         alias_arguments_vector_sp.reset (new OptionArgVector);
331         ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp);
332         AddAlias ("rbreak", cmd_obj_sp);
333         AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp);
334     }
335 }
336 
337 const char *
338 CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
339 {
340     // This function has not yet been implemented.
341 
342     // Look for any embedded script command
343     // If found,
344     //    get interpreter object from the command dictionary,
345     //    call execute_one_command on it,
346     //    get the results as a string,
347     //    substitute that string for current stuff.
348 
349     return arg;
350 }
351 
352 
353 void
354 CommandInterpreter::LoadCommandDictionary ()
355 {
356     Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
357 
358     // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
359     //
360     // Command objects that are used as cross reference objects (i.e. they inherit from CommandObjectCrossref)
361     // *MUST* be created and put into the command dictionary *BEFORE* any multi-word commands (which may use
362     // the cross-referencing stuff) are created!!!
363     //
364     // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
365 
366 
367     // Command objects that inherit from CommandObjectCrossref must be created before other command objects
368     // are created.  This is so that when another command is created that needs to go into a crossref object,
369     // the crossref object exists and is ready to take the cross reference. Put the cross referencing command
370     // objects into the CommandDictionary now, so they are ready for use when the other commands get created.
371 
372     // Non-CommandObjectCrossref commands can now be created.
373 
374     lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
375 
376     m_command_dict["apropos"]   = CommandObjectSP (new CommandObjectApropos (*this));
377     m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
378     //m_command_dict["call"]      = CommandObjectSP (new CommandObjectCall (*this));
379     m_command_dict["command"]   = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
380     m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
381     m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
382 //    m_command_dict["file"]      = CommandObjectSP (new CommandObjectFile (*this));
383     m_command_dict["frame"]     = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
384     m_command_dict["help"]      = CommandObjectSP (new CommandObjectHelp (*this));
385     ///    m_command_dict["image"]     = CommandObjectSP (new CommandObjectImage (*this));
386     m_command_dict["log"]       = CommandObjectSP (new CommandObjectLog (*this));
387     m_command_dict["memory"]    = CommandObjectSP (new CommandObjectMemory (*this));
388     m_command_dict["platform"]  = CommandObjectSP (new CommandObjectPlatform (*this));
389     m_command_dict["plugin"]    = CommandObjectSP (new CommandObjectPlugin (*this));
390     m_command_dict["process"]   = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
391     m_command_dict["quit"]      = CommandObjectSP (new CommandObjectQuit (*this));
392     m_command_dict["register"]  = CommandObjectSP (new CommandObjectRegister (*this));
393     m_command_dict["script"]    = CommandObjectSP (new CommandObjectScript (*this, script_language));
394     m_command_dict["settings"]  = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
395     m_command_dict["source"]    = CommandObjectSP (new CommandObjectMultiwordSource (*this));
396     m_command_dict["target"]    = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
397     m_command_dict["thread"]    = CommandObjectSP (new CommandObjectMultiwordThread (*this));
398     m_command_dict["type"]      = CommandObjectSP (new CommandObjectType (*this));
399     m_command_dict["version"]   = CommandObjectSP (new CommandObjectVersion (*this));
400     m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
401 
402     const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
403                                       {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
404                                       {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
405                                       {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
406                                       {"^(-.*)$", "breakpoint set %1"},
407                                       {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
408                                       {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"},
409                                       {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}};
410 
411     size_t num_regexes = sizeof break_regexes/sizeof(char *[2]);
412 
413     std::auto_ptr<CommandObjectRegexCommand>
414     break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
415                                                       "_regexp-break",
416                                                       "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
417                                                       "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 2));
418 
419     if (break_regex_cmd_ap.get())
420     {
421         bool success = true;
422         for (size_t i = 0; i < num_regexes; i++)
423         {
424             success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]);
425             if (!success)
426                 break;
427         }
428         success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
429 
430         if (success)
431         {
432             CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
433             m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
434         }
435     }
436 
437     std::auto_ptr<CommandObjectRegexCommand>
438     tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this,
439                                                       "_regexp-tbreak",
440                                                       "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
441                                                       "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 2));
442 
443     if (tbreak_regex_cmd_ap.get())
444     {
445         bool success = true;
446         for (size_t i = 0; i < num_regexes; i++)
447         {
448             // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
449             char buffer[1024];
450             int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
451             assert (num_printed < 1024);
452             success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
453             if (!success)
454                 break;
455         }
456         success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
457 
458         if (success)
459         {
460             CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
461             m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp;
462         }
463     }
464 
465     std::auto_ptr<CommandObjectRegexCommand>
466     attach_regex_cmd_ap(new CommandObjectRegexCommand (*this,
467                                                        "_regexp-attach",
468                                                        "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.",
469                                                        "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]", 2));
470     if (attach_regex_cmd_ap.get())
471     {
472         if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") &&
473             attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach'
474             attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") &&
475             attach_regex_cmd_ap->AddRegexCommand("^$", "process attach"))
476         {
477             CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release());
478             m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp;
479         }
480     }
481 
482     std::auto_ptr<CommandObjectRegexCommand>
483     down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
484                                                      "_regexp-down",
485                                                      "Go down \"n\" frames in the stack (1 frame by default).",
486                                                      "_regexp-down [n]", 2));
487     if (down_regex_cmd_ap.get())
488     {
489         if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
490             down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1"))
491         {
492             CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
493             m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
494         }
495     }
496 
497     std::auto_ptr<CommandObjectRegexCommand>
498     up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
499                                                    "_regexp-up",
500                                                    "Go up \"n\" frames in the stack (1 frame by default).",
501                                                    "_regexp-up [n]", 2));
502     if (up_regex_cmd_ap.get())
503     {
504         if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
505             up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1"))
506         {
507             CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
508             m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp;
509         }
510     }
511 
512     std::auto_ptr<CommandObjectRegexCommand>
513     display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
514                                                    "_regexp-display",
515                                                    "Add an expression evaluation stop-hook.",
516                                                    "_regexp-display expression", 2));
517     if (display_regex_cmd_ap.get())
518     {
519         if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
520         {
521             CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release());
522             m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp;
523         }
524     }
525 
526     std::auto_ptr<CommandObjectRegexCommand>
527     undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
528                                                    "_regexp-undisplay",
529                                                    "Remove an expression evaluation stop-hook.",
530                                                    "_regexp-undisplay stop-hook-number", 2));
531     if (undisplay_regex_cmd_ap.get())
532     {
533         if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
534         {
535             CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release());
536             m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp;
537         }
538     }
539 
540     std::auto_ptr<CommandObjectRegexCommand>
541     connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this,
542                                                       "gdb-remote",
543                                                       "Connect to a remote GDB server.  If no hostname is provided, localhost is assumed.",
544                                                       "gdb-remote [<hostname>:]<portnum>", 2));
545     if (connect_gdb_remote_cmd_ap.get())
546     {
547         if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") &&
548             connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1"))
549         {
550             CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release());
551             m_command_dict[command_sp->GetCommandName ()] = command_sp;
552         }
553     }
554 
555     std::auto_ptr<CommandObjectRegexCommand>
556     connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this,
557                                                              "kdp-remote",
558                                                              "Connect to a remote KDP server.  udp port 41139 is the default port number.",
559                                                              "kdp-remote <hostname>[:<portnum>]", 2));
560     if (connect_kdp_remote_cmd_ap.get())
561     {
562         if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
563             connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139"))
564         {
565             CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
566             m_command_dict[command_sp->GetCommandName ()] = command_sp;
567         }
568     }
569 
570     std::auto_ptr<CommandObjectRegexCommand>
571     bt_regex_cmd_ap(new CommandObjectRegexCommand (*this,
572                                                      "_regexp-bt",
573                                                      "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.",
574                                                      "bt [<digit>|all]", 2));
575     if (bt_regex_cmd_ap.get())
576     {
577         // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
578         // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and
579         // so now "bt 3" is the preferred form, in line with gdb.
580         if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") &&
581             bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") &&
582             bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") &&
583             bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace"))
584         {
585             CommandObjectSP command_sp(bt_regex_cmd_ap.release());
586             m_command_dict[command_sp->GetCommandName ()] = command_sp;
587         }
588     }
589 
590     std::auto_ptr<CommandObjectRegexCommand>
591     list_regex_cmd_ap(new CommandObjectRegexCommand (*this,
592                                                      "_regexp-list",
593                                                      "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.",
594                                                      "_regexp-list [<line>]\n_regexp-attach [<file>:<line>]\n_regexp-attach [<file>:<line>]", 2));
595     if (list_regex_cmd_ap.get())
596     {
597         if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") &&
598             list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") &&
599             list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") &&
600             list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") &&
601             list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") &&
602             list_regex_cmd_ap->AddRegexCommand("^$", "source list"))
603         {
604             CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release());
605             m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp;
606         }
607     }
608 
609     std::auto_ptr<CommandObjectRegexCommand>
610     env_regex_cmd_ap(new CommandObjectRegexCommand (*this,
611                                                      "_regexp-env",
612                                                      "Implements a shortcut to viewing and setting environment variables.",
613                                                      "_regexp-env\n_regexp-env FOO=BAR", 2));
614     if (env_regex_cmd_ap.get())
615     {
616         if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") &&
617             env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1"))
618         {
619             CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release());
620             m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp;
621         }
622     }
623 
624 }
625 
626 int
627 CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
628                                                           StringList &matches)
629 {
630     CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
631 
632     if (include_aliases)
633     {
634         CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
635     }
636 
637     return matches.GetSize();
638 }
639 
640 CommandObjectSP
641 CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
642 {
643     CommandObject::CommandMap::iterator pos;
644     CommandObjectSP command_sp;
645 
646     std::string cmd(cmd_cstr);
647 
648     if (HasCommands())
649     {
650         pos = m_command_dict.find(cmd);
651         if (pos != m_command_dict.end())
652             command_sp = pos->second;
653     }
654 
655     if (include_aliases && HasAliases())
656     {
657         pos = m_alias_dict.find(cmd);
658         if (pos != m_alias_dict.end())
659             command_sp = pos->second;
660     }
661 
662     if (HasUserCommands())
663     {
664         pos = m_user_dict.find(cmd);
665         if (pos != m_user_dict.end())
666             command_sp = pos->second;
667     }
668 
669     if (!exact && !command_sp)
670     {
671         // We will only get into here if we didn't find any exact matches.
672 
673         CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
674 
675         StringList local_matches;
676         if (matches == NULL)
677             matches = &local_matches;
678 
679         unsigned int num_cmd_matches = 0;
680         unsigned int num_alias_matches = 0;
681         unsigned int num_user_matches = 0;
682 
683         // Look through the command dictionaries one by one, and if we get only one match from any of
684         // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
685 
686         if (HasCommands())
687         {
688             num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
689         }
690 
691         if (num_cmd_matches == 1)
692         {
693             cmd.assign(matches->GetStringAtIndex(0));
694             pos = m_command_dict.find(cmd);
695             if (pos != m_command_dict.end())
696                 real_match_sp = pos->second;
697         }
698 
699         if (include_aliases && HasAliases())
700         {
701             num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
702 
703         }
704 
705         if (num_alias_matches == 1)
706         {
707             cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
708             pos = m_alias_dict.find(cmd);
709             if (pos != m_alias_dict.end())
710                 alias_match_sp = pos->second;
711         }
712 
713         if (HasUserCommands())
714         {
715             num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
716         }
717 
718         if (num_user_matches == 1)
719         {
720             cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
721 
722             pos = m_user_dict.find (cmd);
723             if (pos != m_user_dict.end())
724                 user_match_sp = pos->second;
725         }
726 
727         // If we got exactly one match, return that, otherwise return the match list.
728 
729         if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
730         {
731             if (num_cmd_matches)
732                 return real_match_sp;
733             else if (num_alias_matches)
734                 return alias_match_sp;
735             else
736                 return user_match_sp;
737         }
738     }
739     else if (matches && command_sp)
740     {
741         matches->AppendString (cmd_cstr);
742     }
743 
744 
745     return command_sp;
746 }
747 
748 bool
749 CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
750 {
751     if (name && name[0])
752     {
753         std::string name_sstr(name);
754         bool found = (m_command_dict.find (name_sstr) != m_command_dict.end());
755         if (found && !can_replace)
756             return false;
757         if (found && m_command_dict[name_sstr]->IsRemovable() == false)
758             return false;
759         m_command_dict[name_sstr] = cmd_sp;
760         return true;
761     }
762     return false;
763 }
764 
765 bool
766 CommandInterpreter::AddUserCommand (std::string name,
767                                     const lldb::CommandObjectSP &cmd_sp,
768                                     bool can_replace)
769 {
770     if (!name.empty())
771     {
772 
773         const char* name_cstr = name.c_str();
774 
775         // do not allow replacement of internal commands
776         if (CommandExists(name_cstr))
777         {
778             if (can_replace == false)
779                 return false;
780             if (m_command_dict[name]->IsRemovable() == false)
781                 return false;
782         }
783 
784         if (UserCommandExists(name_cstr))
785         {
786             if (can_replace == false)
787                 return false;
788             if (m_user_dict[name]->IsRemovable() == false)
789                 return false;
790         }
791 
792         m_user_dict[name] = cmd_sp;
793         return true;
794     }
795     return false;
796 }
797 
798 CommandObjectSP
799 CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
800 {
801     Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
802     CommandObjectSP ret_val;   // Possibly empty return value.
803 
804     if (cmd_cstr == NULL)
805         return ret_val;
806 
807     if (cmd_words.GetArgumentCount() == 1)
808         return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
809     else
810     {
811         // We have a multi-word command (seemingly), so we need to do more work.
812         // First, get the cmd_obj_sp for the first word in the command.
813         CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL);
814         if (cmd_obj_sp.get() != NULL)
815         {
816             // Loop through the rest of the words in the command (everything passed in was supposed to be part of a
817             // command name), and find the appropriate sub-command SP for each command word....
818             size_t end = cmd_words.GetArgumentCount();
819             for (size_t j= 1; j < end; ++j)
820             {
821                 if (cmd_obj_sp->IsMultiwordObject())
822                 {
823                     cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
824                     if (cmd_obj_sp.get() == NULL)
825                         // The sub-command name was invalid.  Fail and return the empty 'ret_val'.
826                         return ret_val;
827                 }
828                 else
829                     // We have more words in the command name, but we don't have a multiword object. Fail and return
830                     // empty 'ret_val'.
831                     return ret_val;
832             }
833             // We successfully looped through all the command words and got valid command objects for them.  Assign the
834             // last object retrieved to 'ret_val'.
835             ret_val = cmd_obj_sp;
836         }
837     }
838     return ret_val;
839 }
840 
841 CommandObject *
842 CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
843 {
844     return GetCommandSPExact (cmd_cstr, include_aliases).get();
845 }
846 
847 CommandObject *
848 CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
849 {
850     CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
851 
852     // If we didn't find an exact match to the command string in the commands, look in
853     // the aliases.
854 
855     if (command_obj == NULL)
856     {
857         command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
858     }
859 
860     // Finally, if there wasn't an exact match among the aliases, look for an inexact match
861     // in both the commands and the aliases.
862 
863     if (command_obj == NULL)
864         command_obj = GetCommandSP(cmd_cstr, true, false, matches).get();
865 
866     return command_obj;
867 }
868 
869 bool
870 CommandInterpreter::CommandExists (const char *cmd)
871 {
872     return m_command_dict.find(cmd) != m_command_dict.end();
873 }
874 
875 bool
876 CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
877                                             const char *options_args,
878                                             OptionArgVectorSP &option_arg_vector_sp)
879 {
880     bool success = true;
881     OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
882 
883     if (!options_args || (strlen (options_args) < 1))
884         return true;
885 
886     std::string options_string (options_args);
887     Args args (options_args);
888     CommandReturnObject result;
889     // Check to see if the command being aliased can take any command options.
890     Options *options = cmd_obj_sp->GetOptions ();
891     if (options)
892     {
893         // See if any options were specified as part of the alias;  if so, handle them appropriately.
894         options->NotifyOptionParsingStarting ();
895         args.Unshift ("dummy_arg");
896         args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
897         args.Shift ();
898         if (result.Succeeded())
899             options->VerifyPartialOptions (result);
900         if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
901         {
902             result.AppendError ("Unable to create requested alias.\n");
903             return false;
904         }
905     }
906 
907     if (!options_string.empty())
908     {
909         if (cmd_obj_sp->WantsRawCommandString ())
910             option_arg_vector->push_back (OptionArgPair ("<argument>",
911                                                           OptionArgValue (-1,
912                                                                           options_string)));
913         else
914         {
915             const size_t argc = args.GetArgumentCount();
916             for (size_t i = 0; i < argc; ++i)
917                 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
918                     option_arg_vector->push_back
919                                 (OptionArgPair ("<argument>",
920                                                 OptionArgValue (-1,
921                                                                 std::string (args.GetArgumentAtIndex (i)))));
922         }
923     }
924 
925     return success;
926 }
927 
928 bool
929 CommandInterpreter::AliasExists (const char *cmd)
930 {
931     return m_alias_dict.find(cmd) != m_alias_dict.end();
932 }
933 
934 bool
935 CommandInterpreter::UserCommandExists (const char *cmd)
936 {
937     return m_user_dict.find(cmd) != m_user_dict.end();
938 }
939 
940 void
941 CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
942 {
943     command_obj_sp->SetIsAlias (true);
944     m_alias_dict[alias_name] = command_obj_sp;
945 }
946 
947 bool
948 CommandInterpreter::RemoveAlias (const char *alias_name)
949 {
950     CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
951     if (pos != m_alias_dict.end())
952     {
953         m_alias_dict.erase(pos);
954         return true;
955     }
956     return false;
957 }
958 bool
959 CommandInterpreter::RemoveUser (const char *alias_name)
960 {
961     CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
962     if (pos != m_user_dict.end())
963     {
964         m_user_dict.erase(pos);
965         return true;
966     }
967     return false;
968 }
969 
970 void
971 CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
972 {
973     help_string.Printf ("'%s", command_name);
974     OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
975 
976     if (option_arg_vector_sp)
977     {
978         OptionArgVector *options = option_arg_vector_sp.get();
979         for (int i = 0; i < options->size(); ++i)
980         {
981             OptionArgPair cur_option = (*options)[i];
982             std::string opt = cur_option.first;
983             OptionArgValue value_pair = cur_option.second;
984             std::string value = value_pair.second;
985             if (opt.compare("<argument>") == 0)
986             {
987                 help_string.Printf (" %s", value.c_str());
988             }
989             else
990             {
991                 help_string.Printf (" %s", opt.c_str());
992                 if ((value.compare ("<no-argument>") != 0)
993                     && (value.compare ("<need-argument") != 0))
994                 {
995                     help_string.Printf (" %s", value.c_str());
996                 }
997             }
998         }
999     }
1000 
1001     help_string.Printf ("'");
1002 }
1003 
1004 size_t
1005 CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
1006 {
1007     CommandObject::CommandMap::const_iterator pos;
1008     CommandObject::CommandMap::const_iterator end = dict.end();
1009     size_t max_len = 0;
1010 
1011     for (pos = dict.begin(); pos != end; ++pos)
1012     {
1013         size_t len = pos->first.size();
1014         if (max_len < len)
1015             max_len = len;
1016     }
1017     return max_len;
1018 }
1019 
1020 void
1021 CommandInterpreter::GetHelp (CommandReturnObject &result,
1022                              uint32_t cmd_types)
1023 {
1024     CommandObject::CommandMap::const_iterator pos;
1025     size_t max_len = FindLongestCommandWord (m_command_dict);
1026 
1027     if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
1028     {
1029 
1030         result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
1031         result.AppendMessage("");
1032 
1033         for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
1034         {
1035             OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1036                                      max_len);
1037         }
1038         result.AppendMessage("");
1039 
1040     }
1041 
1042     if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
1043     {
1044         result.AppendMessage("The following is a list of your current command abbreviations "
1045                              "(see 'help command alias' for more info):");
1046         result.AppendMessage("");
1047         max_len = FindLongestCommandWord (m_alias_dict);
1048 
1049         for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
1050         {
1051             StreamString sstr;
1052             StreamString translation_and_help;
1053             std::string entry_name = pos->first;
1054             std::string second_entry = pos->second.get()->GetCommandName();
1055             GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
1056 
1057             translation_and_help.Printf ("(%s)  %s", sstr.GetData(), pos->second->GetHelp());
1058             OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
1059                                      translation_and_help.GetData(), max_len);
1060         }
1061         result.AppendMessage("");
1062     }
1063 
1064     if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
1065     {
1066         result.AppendMessage ("The following is a list of your current user-defined commands:");
1067         result.AppendMessage("");
1068         max_len = FindLongestCommandWord (m_user_dict);
1069         for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
1070         {
1071             OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1072                                      max_len);
1073         }
1074         result.AppendMessage("");
1075     }
1076 
1077     result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
1078 }
1079 
1080 CommandObject *
1081 CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
1082 {
1083     // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
1084     // eventually be invoked by the given command line.
1085 
1086     CommandObject *cmd_obj = NULL;
1087     std::string white_space (" \t\v");
1088     size_t start = command_string.find_first_not_of (white_space);
1089     size_t end = 0;
1090     bool done = false;
1091     while (!done)
1092     {
1093         if (start != std::string::npos)
1094         {
1095             // Get the next word from command_string.
1096             end = command_string.find_first_of (white_space, start);
1097             if (end == std::string::npos)
1098                 end = command_string.size();
1099             std::string cmd_word = command_string.substr (start, end - start);
1100 
1101             if (cmd_obj == NULL)
1102                 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
1103                 // command or alias.
1104                 cmd_obj = GetCommandObject (cmd_word.c_str());
1105             else if (cmd_obj->IsMultiwordObject ())
1106             {
1107                 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
1108                 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str());
1109                 if (sub_cmd_obj)
1110                     cmd_obj = sub_cmd_obj;
1111                 else // cmd_word was not a valid sub-command word, so we are donee
1112                     done = true;
1113             }
1114             else
1115                 // We have a cmd_obj and it is not a multi-word object, so we are done.
1116                 done = true;
1117 
1118             // If we didn't find a valid command object, or our command object is not a multi-word object, or
1119             // we are at the end of the command_string, then we are done.  Otherwise, find the start of the
1120             // next word.
1121 
1122             if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
1123                 done = true;
1124             else
1125                 start = command_string.find_first_not_of (white_space, end);
1126         }
1127         else
1128             // Unable to find any more words.
1129             done = true;
1130     }
1131 
1132     if (end == command_string.size())
1133         command_string.clear();
1134     else
1135         command_string = command_string.substr(end);
1136 
1137     return cmd_obj;
1138 }
1139 
1140 static const char *k_white_space = " \t\v";
1141 static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1142 static void
1143 StripLeadingSpaces (std::string &s)
1144 {
1145     if (!s.empty())
1146     {
1147         size_t pos = s.find_first_not_of (k_white_space);
1148         if (pos == std::string::npos)
1149             s.clear();
1150         else if (pos == 0)
1151             return;
1152         s.erase (0, pos);
1153     }
1154 }
1155 
1156 static size_t
1157 FindArgumentTerminator (const std::string &s)
1158 {
1159     const size_t s_len = s.size();
1160     size_t offset = 0;
1161     while (offset < s_len)
1162     {
1163         size_t pos = s.find ("--", offset);
1164         if (pos == std::string::npos)
1165             break;
1166         if (pos > 0)
1167         {
1168             if (isspace(s[pos-1]))
1169             {
1170                 // Check if the string ends "\s--" (where \s is a space character)
1171                 // or if we have "\s--\s".
1172                 if ((pos + 2 >= s_len) || isspace(s[pos+2]))
1173                 {
1174                     return pos;
1175                 }
1176             }
1177         }
1178         offset = pos + 2;
1179     }
1180     return std::string::npos;
1181 }
1182 
1183 static bool
1184 ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char &quote_char)
1185 {
1186     command.clear();
1187     suffix.clear();
1188     StripLeadingSpaces (command_string);
1189 
1190     bool result = false;
1191     quote_char = '\0';
1192 
1193     if (!command_string.empty())
1194     {
1195         const char first_char = command_string[0];
1196         if (first_char == '\'' || first_char == '"')
1197         {
1198             quote_char = first_char;
1199             const size_t end_quote_pos = command_string.find (quote_char, 1);
1200             if (end_quote_pos == std::string::npos)
1201             {
1202                 command.swap (command_string);
1203                 command_string.erase ();
1204             }
1205             else
1206             {
1207                 command.assign (command_string, 1, end_quote_pos - 1);
1208                 if (end_quote_pos + 1 < command_string.size())
1209                     command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
1210                 else
1211                     command_string.erase ();
1212             }
1213         }
1214         else
1215         {
1216             const size_t first_space_pos = command_string.find_first_of (k_white_space);
1217             if (first_space_pos == std::string::npos)
1218             {
1219                 command.swap (command_string);
1220                 command_string.erase();
1221             }
1222             else
1223             {
1224                 command.assign (command_string, 0, first_space_pos);
1225                 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
1226             }
1227         }
1228         result = true;
1229     }
1230 
1231 
1232     if (!command.empty())
1233     {
1234         // actual commands can't start with '-' or '_'
1235         if (command[0] != '-' && command[0] != '_')
1236         {
1237             size_t pos = command.find_first_not_of(k_valid_command_chars);
1238             if (pos > 0 && pos != std::string::npos)
1239             {
1240                 suffix.assign (command.begin() + pos, command.end());
1241                 command.erase (pos);
1242             }
1243         }
1244     }
1245 
1246     return result;
1247 }
1248 
1249 CommandObject *
1250 CommandInterpreter::BuildAliasResult (const char *alias_name,
1251                                       std::string &raw_input_string,
1252                                       std::string &alias_result,
1253                                       CommandReturnObject &result)
1254 {
1255     CommandObject *alias_cmd_obj = NULL;
1256     Args cmd_args (raw_input_string.c_str());
1257     alias_cmd_obj = GetCommandObject (alias_name);
1258     StreamString result_str;
1259 
1260     if (alias_cmd_obj)
1261     {
1262         std::string alias_name_str = alias_name;
1263         if ((cmd_args.GetArgumentCount() == 0)
1264             || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
1265             cmd_args.Unshift (alias_name);
1266 
1267         result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
1268         OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1269 
1270         if (option_arg_vector_sp.get())
1271         {
1272             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1273 
1274             for (int i = 0; i < option_arg_vector->size(); ++i)
1275             {
1276                 OptionArgPair option_pair = (*option_arg_vector)[i];
1277                 OptionArgValue value_pair = option_pair.second;
1278                 int value_type = value_pair.first;
1279                 std::string option = option_pair.first;
1280                 std::string value = value_pair.second;
1281                 if (option.compare ("<argument>") == 0)
1282                     result_str.Printf (" %s", value.c_str());
1283                 else
1284                 {
1285                     result_str.Printf (" %s", option.c_str());
1286                     if (value_type != optional_argument)
1287                         result_str.Printf (" ");
1288                     if (value.compare ("<no_argument>") != 0)
1289                     {
1290                         int index = GetOptionArgumentPosition (value.c_str());
1291                         if (index == 0)
1292                             result_str.Printf ("%s", value.c_str());
1293                         else if (index >= cmd_args.GetArgumentCount())
1294                         {
1295 
1296                             result.AppendErrorWithFormat
1297                             ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
1298                              index);
1299                             result.SetStatus (eReturnStatusFailed);
1300                             return alias_cmd_obj;
1301                         }
1302                         else
1303                         {
1304                             size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
1305                             if (strpos != std::string::npos)
1306                                 raw_input_string = raw_input_string.erase (strpos,
1307                                                                           strlen (cmd_args.GetArgumentAtIndex (index)));
1308                             result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
1309                         }
1310                     }
1311                 }
1312             }
1313         }
1314 
1315         alias_result = result_str.GetData();
1316     }
1317     return alias_cmd_obj;
1318 }
1319 
1320 Error
1321 CommandInterpreter::PreprocessCommand (std::string &command)
1322 {
1323     // The command preprocessor needs to do things to the command
1324     // line before any parsing of arguments or anything else is done.
1325     // The only current stuff that gets proprocessed is anyting enclosed
1326     // in backtick ('`') characters is evaluated as an expression and
1327     // the result of the expression must be a scalar that can be substituted
1328     // into the command. An example would be:
1329     // (lldb) memory read `$rsp + 20`
1330     Error error; // Error for any expressions that might not evaluate
1331     size_t start_backtick;
1332     size_t pos = 0;
1333     while ((start_backtick = command.find ('`', pos)) != std::string::npos)
1334     {
1335         if (start_backtick > 0 && command[start_backtick-1] == '\\')
1336         {
1337             // The backtick was preceeded by a '\' character, remove the slash
1338             // and don't treat the backtick as the start of an expression
1339             command.erase(start_backtick-1, 1);
1340             // No need to add one to start_backtick since we just deleted a char
1341             pos = start_backtick;
1342         }
1343         else
1344         {
1345             const size_t expr_content_start = start_backtick + 1;
1346             const size_t end_backtick = command.find ('`', expr_content_start);
1347             if (end_backtick == std::string::npos)
1348                 return error;
1349             else if (end_backtick == expr_content_start)
1350             {
1351                 // Empty expression (two backticks in a row)
1352                 command.erase (start_backtick, 2);
1353             }
1354             else
1355             {
1356                 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
1357 
1358                 ExecutionContext exe_ctx(GetExecutionContext());
1359                 Target *target = exe_ctx.GetTargetPtr();
1360                 // Get a dummy target to allow for calculator mode while processing backticks.
1361                 // This also helps break the infinite loop caused when target is null.
1362                 if (!target)
1363                     target = Host::GetDummyTarget(GetDebugger()).get();
1364                 if (target)
1365                 {
1366                     ValueObjectSP expr_result_valobj_sp;
1367 
1368                     EvaluateExpressionOptions options;
1369                     options.SetCoerceToId(false)
1370                     .SetUnwindOnError(true)
1371                     .SetIgnoreBreakpoints(true)
1372                     .SetKeepInMemory(false)
1373                     .SetRunOthers(true)
1374                     .SetTimeoutUsec(0);
1375 
1376                     ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
1377                                                                                exe_ctx.GetFramePtr(),
1378                                                                                expr_result_valobj_sp,
1379                                                                                options);
1380 
1381                     if (expr_result == eExecutionCompleted)
1382                     {
1383                         Scalar scalar;
1384                         if (expr_result_valobj_sp->ResolveValue (scalar))
1385                         {
1386                             command.erase (start_backtick, end_backtick - start_backtick + 1);
1387                             StreamString value_strm;
1388                             const bool show_type = false;
1389                             scalar.GetValue (&value_strm, show_type);
1390                             size_t value_string_size = value_strm.GetSize();
1391                             if (value_string_size)
1392                             {
1393                                 command.insert (start_backtick, value_strm.GetData(), value_string_size);
1394                                 pos = start_backtick + value_string_size;
1395                                 continue;
1396                             }
1397                             else
1398                             {
1399                                 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1400                             }
1401                         }
1402                         else
1403                         {
1404                             error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1405                         }
1406                     }
1407                     else
1408                     {
1409                         if (expr_result_valobj_sp)
1410                             error = expr_result_valobj_sp->GetError();
1411                         if (error.Success())
1412                         {
1413 
1414                             switch (expr_result)
1415                             {
1416                                 case eExecutionSetupError:
1417                                     error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
1418                                     break;
1419                                 case eExecutionCompleted:
1420                                     break;
1421                                 case eExecutionDiscarded:
1422                                     error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
1423                                     break;
1424                                 case eExecutionInterrupted:
1425                                     error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
1426                                     break;
1427                                 case eExecutionHitBreakpoint:
1428                                     error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
1429                                     break;
1430                                 case eExecutionTimedOut:
1431                                     error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
1432                                     break;
1433                             }
1434                         }
1435                     }
1436                 }
1437             }
1438             if (error.Fail())
1439                 break;
1440         }
1441     }
1442     return error;
1443 }
1444 
1445 
1446 bool
1447 CommandInterpreter::HandleCommand (const char *command_line,
1448                                    LazyBool lazy_add_to_history,
1449                                    CommandReturnObject &result,
1450                                    ExecutionContext *override_context,
1451                                    bool repeat_on_empty_command,
1452                                    bool no_context_switching)
1453 
1454 {
1455 
1456     bool done = false;
1457     CommandObject *cmd_obj = NULL;
1458     bool wants_raw_input = false;
1459     std::string command_string (command_line);
1460     std::string original_command_string (command_line);
1461 
1462     LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
1463     Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
1464 
1465     // Make a scoped cleanup object that will clear the crash description string
1466     // on exit of this function.
1467     lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription);
1468 
1469     if (log)
1470         log->Printf ("Processing command: %s", command_line);
1471 
1472     Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
1473 
1474     if (!no_context_switching)
1475         UpdateExecutionContext (override_context);
1476 
1477     // <rdar://problem/11328896>
1478     bool add_to_history;
1479     if (lazy_add_to_history == eLazyBoolCalculate)
1480         add_to_history = (m_command_source_depth == 0);
1481     else
1482         add_to_history = (lazy_add_to_history == eLazyBoolYes);
1483 
1484     bool empty_command = false;
1485     bool comment_command = false;
1486     if (command_string.empty())
1487         empty_command = true;
1488     else
1489     {
1490         const char *k_space_characters = "\t\n\v\f\r ";
1491 
1492         size_t non_space = command_string.find_first_not_of (k_space_characters);
1493         // Check for empty line or comment line (lines whose first
1494         // non-space character is the comment character for this interpreter)
1495         if (non_space == std::string::npos)
1496             empty_command = true;
1497         else if (command_string[non_space] == m_comment_char)
1498              comment_command = true;
1499         else if (command_string[non_space] == m_repeat_char)
1500         {
1501             const char *history_string = FindHistoryString (command_string.c_str() + non_space);
1502             if (history_string == NULL)
1503             {
1504                 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
1505                 result.SetStatus(eReturnStatusFailed);
1506                 return false;
1507             }
1508             add_to_history = false;
1509             command_string = history_string;
1510             original_command_string = history_string;
1511         }
1512     }
1513 
1514     if (empty_command)
1515     {
1516         if (repeat_on_empty_command)
1517         {
1518             if (m_command_history.empty())
1519             {
1520                 result.AppendError ("empty command");
1521                 result.SetStatus(eReturnStatusFailed);
1522                 return false;
1523             }
1524             else
1525             {
1526                 command_line = m_repeat_command.c_str();
1527                 command_string = command_line;
1528                 original_command_string = command_line;
1529                 if (m_repeat_command.empty())
1530                 {
1531                     result.AppendErrorWithFormat("No auto repeat.\n");
1532                     result.SetStatus (eReturnStatusFailed);
1533                     return false;
1534                 }
1535             }
1536             add_to_history = false;
1537         }
1538         else
1539         {
1540             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1541             return true;
1542         }
1543     }
1544     else if (comment_command)
1545     {
1546         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1547         return true;
1548     }
1549 
1550 
1551     Error error (PreprocessCommand (command_string));
1552 
1553     if (error.Fail())
1554     {
1555         result.AppendError (error.AsCString());
1556         result.SetStatus(eReturnStatusFailed);
1557         return false;
1558     }
1559     // Phase 1.
1560 
1561     // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
1562     // is for the specified command, and whether or not it wants raw input.  This gets complicated by the fact that
1563     // the user could have specified an alias, and in translating the alias there may also be command options and/or
1564     // even data (including raw text strings) that need to be found and inserted into the command line as part of
1565     // the translation.  So this first step is plain look-up & replacement, resulting in three things:  1). the command
1566     // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
1567     // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
1568 
1569     StreamString revised_command_line;
1570     size_t actual_cmd_name_len = 0;
1571     std::string next_word;
1572     StringList matches;
1573     while (!done)
1574     {
1575         char quote_char = '\0';
1576         std::string suffix;
1577         ExtractCommand (command_string, next_word, suffix, quote_char);
1578         if (cmd_obj == NULL)
1579         {
1580             if (AliasExists (next_word.c_str()))
1581             {
1582                 std::string alias_result;
1583                 cmd_obj = BuildAliasResult (next_word.c_str(), command_string, alias_result, result);
1584                 revised_command_line.Printf ("%s", alias_result.c_str());
1585                 if (cmd_obj)
1586                 {
1587                     wants_raw_input = cmd_obj->WantsRawCommandString ();
1588                     actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
1589                 }
1590             }
1591             else
1592             {
1593                 cmd_obj = GetCommandObject (next_word.c_str(), &matches);
1594                 if (cmd_obj)
1595                 {
1596                     actual_cmd_name_len += next_word.length();
1597                     revised_command_line.Printf ("%s", next_word.c_str());
1598                     wants_raw_input = cmd_obj->WantsRawCommandString ();
1599                 }
1600                 else
1601                 {
1602                     revised_command_line.Printf ("%s", next_word.c_str());
1603                 }
1604             }
1605         }
1606         else
1607         {
1608             if (cmd_obj->IsMultiwordObject ())
1609             {
1610                 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str());
1611                 if (sub_cmd_obj)
1612                 {
1613                     actual_cmd_name_len += next_word.length() + 1;
1614                     revised_command_line.Printf (" %s", next_word.c_str());
1615                     cmd_obj = sub_cmd_obj;
1616                     wants_raw_input = cmd_obj->WantsRawCommandString ();
1617                 }
1618                 else
1619                 {
1620                     if (quote_char)
1621                         revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1622                     else
1623                         revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1624                     done = true;
1625                 }
1626             }
1627             else
1628             {
1629                 if (quote_char)
1630                     revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1631                 else
1632                     revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1633                 done = true;
1634             }
1635         }
1636 
1637         if (cmd_obj == NULL)
1638         {
1639             const size_t num_matches = matches.GetSize();
1640             if (matches.GetSize() > 1) {
1641                 StreamString error_msg;
1642                 error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());
1643 
1644                 for (uint32_t i = 0; i < num_matches; ++i) {
1645                     error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i));
1646                 }
1647                 result.AppendRawError (error_msg.GetString().c_str());
1648             } else {
1649                 // We didn't have only one match, otherwise we wouldn't get here.
1650                 assert(num_matches == 0);
1651                 result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
1652             }
1653             result.SetStatus (eReturnStatusFailed);
1654             return false;
1655         }
1656 
1657         if (cmd_obj->IsMultiwordObject ())
1658         {
1659             if (!suffix.empty())
1660             {
1661 
1662                 result.AppendErrorWithFormat ("multi-word commands ('%s') can't have shorthand suffixes: '%s'\n",
1663                                               next_word.c_str(),
1664                                               suffix.c_str());
1665                 result.SetStatus (eReturnStatusFailed);
1666                 return false;
1667             }
1668         }
1669         else
1670         {
1671             // If we found a normal command, we are done
1672             done = true;
1673             if (!suffix.empty())
1674             {
1675                 switch (suffix[0])
1676                 {
1677                 case '/':
1678                     // GDB format suffixes
1679                     {
1680                         Options *command_options = cmd_obj->GetOptions();
1681                         if (command_options && command_options->SupportsLongOption("gdb-format"))
1682                         {
1683                             std::string gdb_format_option ("--gdb-format=");
1684                             gdb_format_option += (suffix.c_str() + 1);
1685 
1686                             bool inserted = false;
1687                             std::string &cmd = revised_command_line.GetString();
1688                             size_t arg_terminator_idx = FindArgumentTerminator (cmd);
1689                             if (arg_terminator_idx != std::string::npos)
1690                             {
1691                                 // Insert the gdb format option before the "--" that terminates options
1692                                 gdb_format_option.append(1,' ');
1693                                 cmd.insert(arg_terminator_idx, gdb_format_option);
1694                                 inserted = true;
1695                             }
1696 
1697                             if (!inserted)
1698                                 revised_command_line.Printf (" %s", gdb_format_option.c_str());
1699 
1700                             if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
1701                                 revised_command_line.PutCString (" --");
1702                         }
1703                         else
1704                         {
1705                             result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n",
1706                                                           cmd_obj->GetCommandName());
1707                             result.SetStatus (eReturnStatusFailed);
1708                             return false;
1709                         }
1710                     }
1711                     break;
1712 
1713                 default:
1714                     result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n",
1715                                                   suffix.c_str());
1716                     result.SetStatus (eReturnStatusFailed);
1717                     return false;
1718 
1719                 }
1720             }
1721         }
1722         if (command_string.length() == 0)
1723             done = true;
1724 
1725     }
1726 
1727     if (!command_string.empty())
1728         revised_command_line.Printf (" %s", command_string.c_str());
1729 
1730     // End of Phase 1.
1731     // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
1732     // specified was valid; revised_command_line contains the complete command line (including command name(s)),
1733     // fully translated with all substitutions & translations taken care of (still in raw text format); and
1734     // wants_raw_input specifies whether the Execute method expects raw input or not.
1735 
1736 
1737     if (log)
1738     {
1739         log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
1740         log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
1741         log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
1742     }
1743 
1744     // Phase 2.
1745     // Take care of things like setting up the history command & calling the appropriate Execute method on the
1746     // CommandObject, with the appropriate arguments.
1747 
1748     if (cmd_obj != NULL)
1749     {
1750         if (add_to_history)
1751         {
1752             Args command_args (revised_command_line.GetData());
1753             const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
1754             if (repeat_command != NULL)
1755                 m_repeat_command.assign(repeat_command);
1756             else
1757                 m_repeat_command.assign(original_command_string.c_str());
1758 
1759             // Don't keep pushing the same command onto the history...
1760             if (m_command_history.empty() || m_command_history.back() != original_command_string)
1761                 m_command_history.push_back (original_command_string);
1762         }
1763 
1764         command_string = revised_command_line.GetData();
1765         std::string command_name (cmd_obj->GetCommandName());
1766         std::string remainder;
1767         if (actual_cmd_name_len < command_string.length())
1768             remainder = command_string.substr (actual_cmd_name_len);  // Note: 'actual_cmd_name_len' may be considerably shorter
1769                                                            // than cmd_obj->GetCommandName(), because name completion
1770                                                            // allows users to enter short versions of the names,
1771                                                            // e.g. 'br s' for 'breakpoint set'.
1772 
1773         // Remove any initial spaces
1774         std::string white_space (" \t\v");
1775         size_t pos = remainder.find_first_not_of (white_space);
1776         if (pos != 0 && pos != std::string::npos)
1777             remainder.erase(0, pos);
1778 
1779         if (log)
1780             log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
1781 
1782         cmd_obj->Execute (remainder.c_str(), result);
1783     }
1784     else
1785     {
1786         // We didn't find the first command object, so complete the first argument.
1787         Args command_args (revised_command_line.GetData());
1788         StringList matches;
1789         int num_matches;
1790         int cursor_index = 0;
1791         int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
1792         bool word_complete;
1793         num_matches = HandleCompletionMatches (command_args,
1794                                                cursor_index,
1795                                                cursor_char_position,
1796                                                0,
1797                                                -1,
1798                                                word_complete,
1799                                                matches);
1800 
1801         if (num_matches > 0)
1802         {
1803             std::string error_msg;
1804             error_msg.assign ("ambiguous command '");
1805             error_msg.append(command_args.GetArgumentAtIndex(0));
1806             error_msg.append ("'.");
1807 
1808             error_msg.append (" Possible completions:");
1809             for (int i = 0; i < num_matches; i++)
1810             {
1811                 error_msg.append ("\n\t");
1812                 error_msg.append (matches.GetStringAtIndex (i));
1813             }
1814             error_msg.append ("\n");
1815             result.AppendRawError (error_msg.c_str());
1816         }
1817         else
1818             result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
1819 
1820         result.SetStatus (eReturnStatusFailed);
1821     }
1822 
1823     if (log)
1824       log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
1825 
1826     return result.Succeeded();
1827 }
1828 
1829 int
1830 CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
1831                                              int &cursor_index,
1832                                              int &cursor_char_position,
1833                                              int match_start_point,
1834                                              int max_return_elements,
1835                                              bool &word_complete,
1836                                              StringList &matches)
1837 {
1838     int num_command_matches = 0;
1839     bool look_for_subcommand = false;
1840 
1841     // For any of the command completions a unique match will be a complete word.
1842     word_complete = true;
1843 
1844     if (cursor_index == -1)
1845     {
1846         // We got nothing on the command line, so return the list of commands
1847         bool include_aliases = true;
1848         num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
1849     }
1850     else if (cursor_index == 0)
1851     {
1852         // The cursor is in the first argument, so just do a lookup in the dictionary.
1853         CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
1854         num_command_matches = matches.GetSize();
1855 
1856         if (num_command_matches == 1
1857             && cmd_obj && cmd_obj->IsMultiwordObject()
1858             && matches.GetStringAtIndex(0) != NULL
1859             && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
1860         {
1861             look_for_subcommand = true;
1862             num_command_matches = 0;
1863             matches.DeleteStringAtIndex(0);
1864             parsed_line.AppendArgument ("");
1865             cursor_index++;
1866             cursor_char_position = 0;
1867         }
1868     }
1869 
1870     if (cursor_index > 0 || look_for_subcommand)
1871     {
1872         // We are completing further on into a commands arguments, so find the command and tell it
1873         // to complete the command.
1874         // First see if there is a matching initial command:
1875         CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
1876         if (command_object == NULL)
1877         {
1878             return 0;
1879         }
1880         else
1881         {
1882             parsed_line.Shift();
1883             cursor_index--;
1884             num_command_matches = command_object->HandleCompletion (parsed_line,
1885                                                                     cursor_index,
1886                                                                     cursor_char_position,
1887                                                                     match_start_point,
1888                                                                     max_return_elements,
1889                                                                     word_complete,
1890                                                                     matches);
1891         }
1892     }
1893 
1894     return num_command_matches;
1895 
1896 }
1897 
1898 int
1899 CommandInterpreter::HandleCompletion (const char *current_line,
1900                                       const char *cursor,
1901                                       const char *last_char,
1902                                       int match_start_point,
1903                                       int max_return_elements,
1904                                       StringList &matches)
1905 {
1906     // We parse the argument up to the cursor, so the last argument in parsed_line is
1907     // the one containing the cursor, and the cursor is after the last character.
1908 
1909     Args parsed_line(current_line, last_char - current_line);
1910     Args partial_parsed_line(current_line, cursor - current_line);
1911 
1912     // Don't complete comments, and if the line we are completing is just the history repeat character,
1913     // substitute the appropriate history line.
1914     const char *first_arg = parsed_line.GetArgumentAtIndex(0);
1915     if (first_arg)
1916     {
1917         if (first_arg[0] == m_comment_char)
1918             return 0;
1919         else if (first_arg[0] == m_repeat_char)
1920         {
1921             const char *history_string = FindHistoryString (first_arg);
1922             if (history_string != NULL)
1923             {
1924                 matches.Clear();
1925                 matches.InsertStringAtIndex(0, history_string);
1926                 return -2;
1927             }
1928             else
1929                 return 0;
1930 
1931         }
1932     }
1933 
1934 
1935     int num_args = partial_parsed_line.GetArgumentCount();
1936     int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
1937     int cursor_char_position;
1938 
1939     if (cursor_index == -1)
1940         cursor_char_position = 0;
1941     else
1942         cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
1943 
1944     if (cursor > current_line && cursor[-1] == ' ')
1945     {
1946         // We are just after a space.  If we are in an argument, then we will continue
1947         // parsing, but if we are between arguments, then we have to complete whatever the next
1948         // element would be.
1949         // We can distinguish the two cases because if we are in an argument (e.g. because the space is
1950         // protected by a quote) then the space will also be in the parsed argument...
1951 
1952         const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
1953         if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
1954         {
1955             parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '"');
1956             cursor_index++;
1957             cursor_char_position = 0;
1958         }
1959     }
1960 
1961     int num_command_matches;
1962 
1963     matches.Clear();
1964 
1965     // Only max_return_elements == -1 is supported at present:
1966     assert (max_return_elements == -1);
1967     bool word_complete;
1968     num_command_matches = HandleCompletionMatches (parsed_line,
1969                                                    cursor_index,
1970                                                    cursor_char_position,
1971                                                    match_start_point,
1972                                                    max_return_elements,
1973                                                    word_complete,
1974                                                    matches);
1975 
1976     if (num_command_matches <= 0)
1977             return num_command_matches;
1978 
1979     if (num_args == 0)
1980     {
1981         // If we got an empty string, insert nothing.
1982         matches.InsertStringAtIndex(0, "");
1983     }
1984     else
1985     {
1986         // Now figure out if there is a common substring, and if so put that in element 0, otherwise
1987         // put an empty string in element 0.
1988         std::string command_partial_str;
1989         if (cursor_index >= 0)
1990             command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
1991                                        parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
1992 
1993         std::string common_prefix;
1994         matches.LongestCommonPrefix (common_prefix);
1995         const size_t partial_name_len = command_partial_str.size();
1996 
1997         // If we matched a unique single command, add a space...
1998         // Only do this if the completer told us this was a complete word, however...
1999         if (num_command_matches == 1 && word_complete)
2000         {
2001             char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
2002             if (quote_char != '\0')
2003                 common_prefix.push_back(quote_char);
2004 
2005             common_prefix.push_back(' ');
2006         }
2007         common_prefix.erase (0, partial_name_len);
2008         matches.InsertStringAtIndex(0, common_prefix.c_str());
2009     }
2010     return num_command_matches;
2011 }
2012 
2013 
2014 CommandInterpreter::~CommandInterpreter ()
2015 {
2016 }
2017 
2018 const char *
2019 CommandInterpreter::GetPrompt ()
2020 {
2021     return m_debugger.GetPrompt();
2022 }
2023 
2024 void
2025 CommandInterpreter::SetPrompt (const char *new_prompt)
2026 {
2027     m_debugger.SetPrompt (new_prompt);
2028 }
2029 
2030 size_t
2031 CommandInterpreter::GetConfirmationInputReaderCallback
2032 (
2033     void *baton,
2034     InputReader &reader,
2035     lldb::InputReaderAction action,
2036     const char *bytes,
2037     size_t bytes_len
2038 )
2039 {
2040     File &out_file = reader.GetDebugger().GetOutputFile();
2041     bool *response_ptr = (bool *) baton;
2042 
2043     switch (action)
2044     {
2045     case eInputReaderActivate:
2046         if (out_file.IsValid())
2047         {
2048             if (reader.GetPrompt())
2049             {
2050                 out_file.Printf ("%s", reader.GetPrompt());
2051                 out_file.Flush ();
2052             }
2053         }
2054         break;
2055 
2056     case eInputReaderDeactivate:
2057         break;
2058 
2059     case eInputReaderReactivate:
2060         if (out_file.IsValid() && reader.GetPrompt())
2061         {
2062             out_file.Printf ("%s", reader.GetPrompt());
2063             out_file.Flush ();
2064         }
2065         break;
2066 
2067     case eInputReaderAsynchronousOutputWritten:
2068         break;
2069 
2070     case eInputReaderGotToken:
2071         if (bytes_len == 0)
2072         {
2073             reader.SetIsDone(true);
2074         }
2075         else if (bytes[0] == 'y' || bytes[0] == 'Y')
2076         {
2077             *response_ptr = true;
2078             reader.SetIsDone(true);
2079         }
2080         else if (bytes[0] == 'n' || bytes[0] == 'N')
2081         {
2082             *response_ptr = false;
2083             reader.SetIsDone(true);
2084         }
2085         else
2086         {
2087             if (out_file.IsValid() && !reader.IsDone() && reader.GetPrompt())
2088             {
2089                 out_file.Printf ("Please answer \"y\" or \"n\".\n%s", reader.GetPrompt());
2090                 out_file.Flush ();
2091             }
2092         }
2093         break;
2094 
2095     case eInputReaderInterrupt:
2096     case eInputReaderEndOfFile:
2097         *response_ptr = false;  // Assume ^C or ^D means cancel the proposed action
2098         reader.SetIsDone (true);
2099         break;
2100 
2101     case eInputReaderDone:
2102         break;
2103     }
2104 
2105     return bytes_len;
2106 
2107 }
2108 
2109 bool
2110 CommandInterpreter::Confirm (const char *message, bool default_answer)
2111 {
2112     // Check AutoConfirm first:
2113     if (m_debugger.GetAutoConfirm())
2114         return default_answer;
2115 
2116     InputReaderSP reader_sp (new InputReader(GetDebugger()));
2117     bool response = default_answer;
2118     if (reader_sp)
2119     {
2120         std::string prompt(message);
2121         prompt.append(": [");
2122         if (default_answer)
2123             prompt.append ("Y/n] ");
2124         else
2125             prompt.append ("y/N] ");
2126 
2127         Error err (reader_sp->Initialize (CommandInterpreter::GetConfirmationInputReaderCallback,
2128                                           &response,                    // baton
2129                                           eInputReaderGranularityLine,  // token size, to pass to callback function
2130                                           NULL,                         // end token
2131                                           prompt.c_str(),               // prompt
2132                                           true));                       // echo input
2133         if (err.Success())
2134         {
2135             GetDebugger().PushInputReader (reader_sp);
2136         }
2137         reader_sp->WaitOnReaderIsDone();
2138     }
2139     return response;
2140 }
2141 
2142 
2143 void
2144 CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
2145 {
2146     CommandObjectSP cmd_obj_sp = GetCommandSPExact (dest_cmd, true);
2147 
2148     if (cmd_obj_sp)
2149     {
2150         CommandObject *cmd_obj = cmd_obj_sp.get();
2151         if (cmd_obj->IsCrossRefObject ())
2152             cmd_obj->AddObject (object_type);
2153     }
2154 }
2155 
2156 OptionArgVectorSP
2157 CommandInterpreter::GetAliasOptions (const char *alias_name)
2158 {
2159     OptionArgMap::iterator pos;
2160     OptionArgVectorSP ret_val;
2161 
2162     std::string alias (alias_name);
2163 
2164     if (HasAliasOptions())
2165     {
2166         pos = m_alias_options.find (alias);
2167         if (pos != m_alias_options.end())
2168           ret_val = pos->second;
2169     }
2170 
2171     return ret_val;
2172 }
2173 
2174 void
2175 CommandInterpreter::RemoveAliasOptions (const char *alias_name)
2176 {
2177     OptionArgMap::iterator pos = m_alias_options.find(alias_name);
2178     if (pos != m_alias_options.end())
2179     {
2180         m_alias_options.erase (pos);
2181     }
2182 }
2183 
2184 void
2185 CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
2186 {
2187     m_alias_options[alias_name] = option_arg_vector_sp;
2188 }
2189 
2190 bool
2191 CommandInterpreter::HasCommands ()
2192 {
2193     return (!m_command_dict.empty());
2194 }
2195 
2196 bool
2197 CommandInterpreter::HasAliases ()
2198 {
2199     return (!m_alias_dict.empty());
2200 }
2201 
2202 bool
2203 CommandInterpreter::HasUserCommands ()
2204 {
2205     return (!m_user_dict.empty());
2206 }
2207 
2208 bool
2209 CommandInterpreter::HasAliasOptions ()
2210 {
2211     return (!m_alias_options.empty());
2212 }
2213 
2214 void
2215 CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
2216                                            const char *alias_name,
2217                                            Args &cmd_args,
2218                                            std::string &raw_input_string,
2219                                            CommandReturnObject &result)
2220 {
2221     OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
2222 
2223     bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
2224 
2225     // Make sure that the alias name is the 0th element in cmd_args
2226     std::string alias_name_str = alias_name;
2227     if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
2228         cmd_args.Unshift (alias_name);
2229 
2230     Args new_args (alias_cmd_obj->GetCommandName());
2231     if (new_args.GetArgumentCount() == 2)
2232         new_args.Shift();
2233 
2234     if (option_arg_vector_sp.get())
2235     {
2236         if (wants_raw_input)
2237         {
2238             // We have a command that both has command options and takes raw input.  Make *sure* it has a
2239             // " -- " in the right place in the raw_input_string.
2240             size_t pos = raw_input_string.find(" -- ");
2241             if (pos == std::string::npos)
2242             {
2243                 // None found; assume it goes at the beginning of the raw input string
2244                 raw_input_string.insert (0, " -- ");
2245             }
2246         }
2247 
2248         OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
2249         const size_t old_size = cmd_args.GetArgumentCount();
2250         std::vector<bool> used (old_size + 1, false);
2251 
2252         used[0] = true;
2253 
2254         for (int i = 0; i < option_arg_vector->size(); ++i)
2255         {
2256             OptionArgPair option_pair = (*option_arg_vector)[i];
2257             OptionArgValue value_pair = option_pair.second;
2258             int value_type = value_pair.first;
2259             std::string option = option_pair.first;
2260             std::string value = value_pair.second;
2261             if (option.compare ("<argument>") == 0)
2262             {
2263                 if (!wants_raw_input
2264                     || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
2265                     new_args.AppendArgument (value.c_str());
2266             }
2267             else
2268             {
2269                 if (value_type != optional_argument)
2270                     new_args.AppendArgument (option.c_str());
2271                 if (value.compare ("<no-argument>") != 0)
2272                 {
2273                     int index = GetOptionArgumentPosition (value.c_str());
2274                     if (index == 0)
2275                     {
2276                         // value was NOT a positional argument; must be a real value
2277                         if (value_type != optional_argument)
2278                             new_args.AppendArgument (value.c_str());
2279                         else
2280                         {
2281                             char buffer[255];
2282                             ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
2283                             new_args.AppendArgument (buffer);
2284                         }
2285 
2286                     }
2287                     else if (index >= cmd_args.GetArgumentCount())
2288                     {
2289                         result.AppendErrorWithFormat
2290                                     ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
2291                                      index);
2292                         result.SetStatus (eReturnStatusFailed);
2293                         return;
2294                     }
2295                     else
2296                     {
2297                         // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2298                         size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
2299                         if (strpos != std::string::npos)
2300                         {
2301                             raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
2302                         }
2303 
2304                         if (value_type != optional_argument)
2305                             new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
2306                         else
2307                         {
2308                             char buffer[255];
2309                             ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
2310                                         cmd_args.GetArgumentAtIndex (index));
2311                             new_args.AppendArgument (buffer);
2312                         }
2313                         used[index] = true;
2314                     }
2315                 }
2316             }
2317         }
2318 
2319         for (int j = 0; j < cmd_args.GetArgumentCount(); ++j)
2320         {
2321             if (!used[j] && !wants_raw_input)
2322                 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
2323         }
2324 
2325         cmd_args.Clear();
2326         cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2327     }
2328     else
2329     {
2330         result.SetStatus (eReturnStatusSuccessFinishNoResult);
2331         // This alias was not created with any options; nothing further needs to be done, unless it is a command that
2332         // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
2333         // input string.
2334         if (wants_raw_input)
2335         {
2336             cmd_args.Clear();
2337             cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2338         }
2339         return;
2340     }
2341 
2342     result.SetStatus (eReturnStatusSuccessFinishNoResult);
2343     return;
2344 }
2345 
2346 
2347 int
2348 CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
2349 {
2350     int position = 0;   // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
2351                         // of zero.
2352 
2353     char *cptr = (char *) in_string;
2354 
2355     // Does it start with '%'
2356     if (cptr[0] == '%')
2357     {
2358         ++cptr;
2359 
2360         // Is the rest of it entirely digits?
2361         if (isdigit (cptr[0]))
2362         {
2363             const char *start = cptr;
2364             while (isdigit (cptr[0]))
2365                 ++cptr;
2366 
2367             // We've gotten to the end of the digits; are we at the end of the string?
2368             if (cptr[0] == '\0')
2369                 position = atoi (start);
2370         }
2371     }
2372 
2373     return position;
2374 }
2375 
2376 void
2377 CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
2378 {
2379     FileSpec init_file;
2380     if (in_cwd)
2381     {
2382         // In the current working directory we don't load any program specific
2383         // .lldbinit files, we only look for a "./.lldbinit" file.
2384         if (m_skip_lldbinit_files)
2385             return;
2386 
2387         init_file.SetFile ("./.lldbinit", true);
2388     }
2389     else
2390     {
2391         // If we aren't looking in the current working directory we are looking
2392         // in the home directory. We will first see if there is an application
2393         // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
2394         // "-" and the name of the program. If this file doesn't exist, we fall
2395         // back to just the "~/.lldbinit" file. We also obey any requests to not
2396         // load the init files.
2397         const char *init_file_path = "~/.lldbinit";
2398 
2399         if (m_skip_app_init_files == false)
2400         {
2401             FileSpec program_file_spec (Host::GetProgramFileSpec());
2402             const char *program_name = program_file_spec.GetFilename().AsCString();
2403 
2404             if (program_name)
2405             {
2406                 char program_init_file_name[PATH_MAX];
2407                 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name);
2408                 init_file.SetFile (program_init_file_name, true);
2409                 if (!init_file.Exists())
2410                     init_file.Clear();
2411             }
2412         }
2413 
2414         if (!init_file && !m_skip_lldbinit_files)
2415 			init_file.SetFile (init_file_path, true);
2416     }
2417 
2418     // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
2419     // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
2420 
2421     if (init_file.Exists())
2422     {
2423         ExecutionContext *exe_ctx = NULL;  // We don't have any context yet.
2424         bool stop_on_continue = true;
2425         bool stop_on_error    = false;
2426         bool echo_commands    = false;
2427         bool print_results    = false;
2428 
2429         HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, eLazyBoolNo, result);
2430     }
2431     else
2432     {
2433         // nothing to be done if the file doesn't exist
2434         result.SetStatus(eReturnStatusSuccessFinishNoResult);
2435     }
2436 }
2437 
2438 PlatformSP
2439 CommandInterpreter::GetPlatform (bool prefer_target_platform)
2440 {
2441     PlatformSP platform_sp;
2442     if (prefer_target_platform)
2443     {
2444         ExecutionContext exe_ctx(GetExecutionContext());
2445         Target *target = exe_ctx.GetTargetPtr();
2446         if (target)
2447             platform_sp = target->GetPlatform();
2448     }
2449 
2450     if (!platform_sp)
2451         platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
2452     return platform_sp;
2453 }
2454 
2455 void
2456 CommandInterpreter::HandleCommands (const StringList &commands,
2457                                     ExecutionContext *override_context,
2458                                     bool stop_on_continue,
2459                                     bool stop_on_error,
2460                                     bool echo_commands,
2461                                     bool print_results,
2462                                     LazyBool add_to_history,
2463                                     CommandReturnObject &result)
2464 {
2465     size_t num_lines = commands.GetSize();
2466 
2467     // If we are going to continue past a "continue" then we need to run the commands synchronously.
2468     // Make sure you reset this value anywhere you return from the function.
2469 
2470     bool old_async_execution = m_debugger.GetAsyncExecution();
2471 
2472     // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
2473     // cause series of commands that change the context, then do an operation that relies on that context to fail.
2474 
2475     if (override_context != NULL)
2476         UpdateExecutionContext (override_context);
2477 
2478     if (!stop_on_continue)
2479     {
2480         m_debugger.SetAsyncExecution (false);
2481     }
2482 
2483     for (int idx = 0; idx < num_lines; idx++)
2484     {
2485         const char *cmd = commands.GetStringAtIndex(idx);
2486         if (cmd[0] == '\0')
2487             continue;
2488 
2489         if (echo_commands)
2490         {
2491             result.AppendMessageWithFormat ("%s %s\n",
2492                                              GetPrompt(),
2493                                              cmd);
2494         }
2495 
2496         CommandReturnObject tmp_result;
2497         // If override_context is not NULL, pass no_context_switching = true for
2498         // HandleCommand() since we updated our context already.
2499         bool success = HandleCommand(cmd, add_to_history, tmp_result,
2500                                      NULL, /* override_context */
2501                                      true, /* repeat_on_empty_command */
2502                                      override_context != NULL /* no_context_switching */);
2503 
2504         if (print_results)
2505         {
2506             if (tmp_result.Succeeded())
2507               result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
2508         }
2509 
2510         if (!success || !tmp_result.Succeeded())
2511         {
2512             const char *error_msg = tmp_result.GetErrorData();
2513             if (error_msg == NULL || error_msg[0] == '\0')
2514                 error_msg = "<unknown error>.\n";
2515             if (stop_on_error)
2516             {
2517                 result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' failed with %s",
2518                                          idx, cmd, error_msg);
2519                 result.SetStatus (eReturnStatusFailed);
2520                 m_debugger.SetAsyncExecution (old_async_execution);
2521                 return;
2522             }
2523             else if (print_results)
2524             {
2525                 result.AppendMessageWithFormat ("Command #%d '%s' failed with %s",
2526                                                 idx + 1,
2527                                                 cmd,
2528                                                 error_msg);
2529             }
2530         }
2531 
2532         if (result.GetImmediateOutputStream())
2533             result.GetImmediateOutputStream()->Flush();
2534 
2535         if (result.GetImmediateErrorStream())
2536             result.GetImmediateErrorStream()->Flush();
2537 
2538         // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
2539         // could be running (for instance in Breakpoint Commands.
2540         // So we check the return value to see if it is has running in it.
2541         if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
2542                 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
2543         {
2544             if (stop_on_continue)
2545             {
2546                 // If we caused the target to proceed, and we're going to stop in that case, set the
2547                 // status in our real result before returning.  This is an error if the continue was not the
2548                 // last command in the set of commands to be run.
2549                 if (idx != num_lines - 1)
2550                     result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' continued the target.\n",
2551                                                  idx + 1, cmd);
2552                 else
2553                     result.AppendMessageWithFormat ("Command #%d '%s' continued the target.\n", idx + 1, cmd);
2554 
2555                 result.SetStatus(tmp_result.GetStatus());
2556                 m_debugger.SetAsyncExecution (old_async_execution);
2557 
2558                 return;
2559             }
2560         }
2561 
2562     }
2563 
2564     result.SetStatus (eReturnStatusSuccessFinishResult);
2565     m_debugger.SetAsyncExecution (old_async_execution);
2566 
2567     return;
2568 }
2569 
2570 void
2571 CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
2572                                             ExecutionContext *context,
2573                                             bool stop_on_continue,
2574                                             bool stop_on_error,
2575                                             bool echo_command,
2576                                             bool print_result,
2577                                             LazyBool add_to_history,
2578                                             CommandReturnObject &result)
2579 {
2580     if (cmd_file.Exists())
2581     {
2582         bool success;
2583         StringList commands;
2584         success = commands.ReadFileLines(cmd_file);
2585         if (!success)
2586         {
2587             result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString());
2588             result.SetStatus (eReturnStatusFailed);
2589             return;
2590         }
2591         m_command_source_depth++;
2592         HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, add_to_history, result);
2593         m_command_source_depth--;
2594     }
2595     else
2596     {
2597         result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
2598                                       cmd_file.GetFilename().AsCString());
2599         result.SetStatus (eReturnStatusFailed);
2600         return;
2601     }
2602 }
2603 
2604 ScriptInterpreter *
2605 CommandInterpreter::GetScriptInterpreter (bool can_create)
2606 {
2607     if (m_script_interpreter_ap.get() != NULL)
2608         return m_script_interpreter_ap.get();
2609 
2610     if (!can_create)
2611         return NULL;
2612 
2613     // <rdar://problem/11751427>
2614     // we need to protect the initialization of the script interpreter
2615     // otherwise we could end up with two threads both trying to create
2616     // their instance of it, and for some languages (e.g. Python)
2617     // this is a bulletproof recipe for disaster!
2618     // this needs to be a function-level static because multiple Debugger instances living in the same process
2619     // still need to be isolated and not try to initialize Python concurrently
2620     static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
2621     Mutex::Locker interpreter_lock(g_interpreter_mutex);
2622 
2623     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
2624     if (log)
2625         log->Printf("Initializing the ScriptInterpreter now\n");
2626 
2627     lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
2628     switch (script_lang)
2629     {
2630         case eScriptLanguagePython:
2631 #ifndef LLDB_DISABLE_PYTHON
2632             m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
2633             break;
2634 #else
2635             // Fall through to the None case when python is disabled
2636 #endif
2637         case eScriptLanguageNone:
2638             m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
2639             break;
2640     };
2641 
2642     return m_script_interpreter_ap.get();
2643 }
2644 
2645 
2646 
2647 bool
2648 CommandInterpreter::GetSynchronous ()
2649 {
2650     return m_synchronous_execution;
2651 }
2652 
2653 void
2654 CommandInterpreter::SetSynchronous (bool value)
2655 {
2656     m_synchronous_execution  = value;
2657 }
2658 
2659 void
2660 CommandInterpreter::OutputFormattedHelpText (Stream &strm,
2661                                              const char *word_text,
2662                                              const char *separator,
2663                                              const char *help_text,
2664                                              size_t max_word_len)
2665 {
2666     const uint32_t max_columns = m_debugger.GetTerminalWidth();
2667 
2668     int indent_size = max_word_len + strlen (separator) + 2;
2669 
2670     strm.IndentMore (indent_size);
2671 
2672     StreamString text_strm;
2673     text_strm.Printf ("%-*s %s %s",  (int)max_word_len, word_text, separator, help_text);
2674 
2675     size_t len = text_strm.GetSize();
2676     const char *text = text_strm.GetData();
2677     if (text[len - 1] == '\n')
2678     {
2679         text_strm.EOL();
2680         len = text_strm.GetSize();
2681     }
2682 
2683     if (len  < max_columns)
2684     {
2685         // Output it as a single line.
2686         strm.Printf ("%s", text);
2687     }
2688     else
2689     {
2690         // We need to break it up into multiple lines.
2691         bool first_line = true;
2692         int text_width;
2693         size_t start = 0;
2694         size_t end = start;
2695         const size_t final_end = strlen (text);
2696 
2697         while (end < final_end)
2698         {
2699             if (first_line)
2700                 text_width = max_columns - 1;
2701             else
2702                 text_width = max_columns - indent_size - 1;
2703 
2704             // Don't start the 'text' on a space, since we're already outputting the indentation.
2705             if (!first_line)
2706             {
2707                 while ((start < final_end) && (text[start] == ' '))
2708                   start++;
2709             }
2710 
2711             end = start + text_width;
2712             if (end > final_end)
2713                 end = final_end;
2714             else
2715             {
2716                 // If we're not at the end of the text, make sure we break the line on white space.
2717                 while (end > start
2718                        && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
2719                     end--;
2720                 assert (end > 0);
2721             }
2722 
2723             const size_t sub_len = end - start;
2724             if (start != 0)
2725               strm.EOL();
2726             if (!first_line)
2727                 strm.Indent();
2728             else
2729                 first_line = false;
2730             assert (start <= final_end);
2731             assert (start + sub_len <= final_end);
2732             if (sub_len > 0)
2733                 strm.Write (text + start, sub_len);
2734             start = end + 1;
2735         }
2736     }
2737     strm.EOL();
2738     strm.IndentLess(indent_size);
2739 }
2740 
2741 void
2742 CommandInterpreter::OutputHelpText (Stream &strm,
2743                                     const char *word_text,
2744                                     const char *separator,
2745                                     const char *help_text,
2746                                     uint32_t max_word_len)
2747 {
2748     int indent_size = max_word_len + strlen (separator) + 2;
2749 
2750     strm.IndentMore (indent_size);
2751 
2752     StreamString text_strm;
2753     text_strm.Printf ("%-*s %s %s",  max_word_len, word_text, separator, help_text);
2754 
2755     const uint32_t max_columns = m_debugger.GetTerminalWidth();
2756 
2757     size_t len = text_strm.GetSize();
2758     const char *text = text_strm.GetData();
2759 
2760     uint32_t chars_left = max_columns;
2761 
2762     for (uint32_t i = 0; i < len; i++)
2763     {
2764         if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
2765         {
2766             chars_left = max_columns - indent_size;
2767             strm.EOL();
2768             strm.Indent();
2769         }
2770         else
2771         {
2772             strm.PutChar(text[i]);
2773             chars_left--;
2774         }
2775 
2776     }
2777 
2778     strm.EOL();
2779     strm.IndentLess(indent_size);
2780 }
2781 
2782 void
2783 CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
2784                                             StringList &commands_help)
2785 {
2786     CommandObject::CommandMap::const_iterator pos;
2787 
2788     for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
2789     {
2790         const char *command_name = pos->first.c_str();
2791         CommandObject *cmd_obj = pos->second.get();
2792 
2793         if (cmd_obj->HelpTextContainsWord (search_word))
2794         {
2795             commands_found.AppendString (command_name);
2796             commands_help.AppendString (cmd_obj->GetHelp());
2797         }
2798 
2799         if (cmd_obj->IsMultiwordObject())
2800             cmd_obj->AproposAllSubCommands (command_name,
2801                                             search_word,
2802                                             commands_found,
2803                                             commands_help);
2804 
2805     }
2806 }
2807 
2808 
2809 void
2810 CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
2811 {
2812     if (override_context != NULL)
2813     {
2814         m_exe_ctx_ref = *override_context;
2815     }
2816     else
2817     {
2818         const bool adopt_selected = true;
2819         m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
2820     }
2821 }
2822 
2823 void
2824 CommandInterpreter::DumpHistory (Stream &stream, uint32_t count) const
2825 {
2826     DumpHistory (stream, 0, count - 1);
2827 }
2828 
2829 void
2830 CommandInterpreter::DumpHistory (Stream &stream, uint32_t start, uint32_t end) const
2831 {
2832     const size_t last_idx = std::min<size_t>(m_command_history.size(), end + 1);
2833     for (size_t i = start; i < last_idx; i++)
2834     {
2835         if (!m_command_history[i].empty())
2836         {
2837             stream.Indent();
2838             stream.Printf ("%4zu: %s\n", i, m_command_history[i].c_str());
2839         }
2840     }
2841 }
2842 
2843 const char *
2844 CommandInterpreter::FindHistoryString (const char *input_str) const
2845 {
2846     if (input_str[0] != m_repeat_char)
2847         return NULL;
2848     if (input_str[1] == '-')
2849     {
2850         bool success;
2851         size_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success);
2852         if (!success)
2853             return NULL;
2854         if (idx > m_command_history.size())
2855             return NULL;
2856         idx = m_command_history.size() - idx;
2857         return m_command_history[idx].c_str();
2858 
2859     }
2860     else if (input_str[1] == m_repeat_char)
2861     {
2862         if (m_command_history.empty())
2863             return NULL;
2864         else
2865             return m_command_history.back().c_str();
2866     }
2867     else
2868     {
2869         bool success;
2870         uint32_t idx = Args::StringToUInt32 (input_str+1, 0, 0, &success);
2871         if (!success)
2872             return NULL;
2873         if (idx >= m_command_history.size())
2874             return NULL;
2875         return m_command_history[idx].c_str();
2876     }
2877 }
2878