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