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         if (!can_replace)
628         {
629             if (m_command_dict.find (name_sstr) != m_command_dict.end())
630                 return false;
631         }
632         if (m_command_dict[name_sstr]->IsRemovable() == false)
633             return false;
634         m_command_dict[name_sstr] = cmd_sp;
635         return true;
636     }
637     return false;
638 }
639 
640 bool
641 CommandInterpreter::AddUserCommand (std::string name,
642                                     const lldb::CommandObjectSP &cmd_sp,
643                                     bool can_replace)
644 {
645     if (!name.empty())
646     {
647 
648         const char* name_cstr = name.c_str();
649 
650         // do not allow replacement of internal commands
651         if (CommandExists(name_cstr))
652         {
653             if (can_replace == false)
654                 return false;
655             if (m_command_dict[name]->IsRemovable() == false)
656                 return false;
657         }
658 
659         if (UserCommandExists(name_cstr))
660         {
661             if (can_replace == false)
662                 return false;
663             if (m_user_dict[name]->IsRemovable() == false)
664                 return false;
665         }
666 
667         m_user_dict[name] = cmd_sp;
668         return true;
669     }
670     return false;
671 }
672 
673 CommandObjectSP
674 CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
675 {
676     Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
677     CommandObjectSP ret_val;   // Possibly empty return value.
678 
679     if (cmd_cstr == NULL)
680         return ret_val;
681 
682     if (cmd_words.GetArgumentCount() == 1)
683         return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
684     else
685     {
686         // We have a multi-word command (seemingly), so we need to do more work.
687         // First, get the cmd_obj_sp for the first word in the command.
688         CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL);
689         if (cmd_obj_sp.get() != NULL)
690         {
691             // Loop through the rest of the words in the command (everything passed in was supposed to be part of a
692             // command name), and find the appropriate sub-command SP for each command word....
693             size_t end = cmd_words.GetArgumentCount();
694             for (size_t j= 1; j < end; ++j)
695             {
696                 if (cmd_obj_sp->IsMultiwordObject())
697                 {
698                     cmd_obj_sp = ((CommandObjectMultiword *) cmd_obj_sp.get())->GetSubcommandSP
699                     (cmd_words.GetArgumentAtIndex (j));
700                     if (cmd_obj_sp.get() == NULL)
701                         // The sub-command name was invalid.  Fail and return the empty 'ret_val'.
702                         return ret_val;
703                 }
704                 else
705                     // We have more words in the command name, but we don't have a multiword object. Fail and return
706                     // empty 'ret_val'.
707                     return ret_val;
708             }
709             // We successfully looped through all the command words and got valid command objects for them.  Assign the
710             // last object retrieved to 'ret_val'.
711             ret_val = cmd_obj_sp;
712         }
713     }
714     return ret_val;
715 }
716 
717 CommandObject *
718 CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
719 {
720     return GetCommandSPExact (cmd_cstr, include_aliases).get();
721 }
722 
723 CommandObject *
724 CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
725 {
726     CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
727 
728     // If we didn't find an exact match to the command string in the commands, look in
729     // the aliases.
730 
731     if (command_obj == NULL)
732     {
733         command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
734     }
735 
736     // Finally, if there wasn't an exact match among the aliases, look for an inexact match
737     // in both the commands and the aliases.
738 
739     if (command_obj == NULL)
740         command_obj = GetCommandSP(cmd_cstr, true, false, matches).get();
741 
742     return command_obj;
743 }
744 
745 bool
746 CommandInterpreter::CommandExists (const char *cmd)
747 {
748     return m_command_dict.find(cmd) != m_command_dict.end();
749 }
750 
751 bool
752 CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
753                                             const char *options_args,
754                                             OptionArgVectorSP &option_arg_vector_sp)
755 {
756     bool success = true;
757     OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
758 
759     if (!options_args || (strlen (options_args) < 1))
760         return true;
761 
762     std::string options_string (options_args);
763     Args args (options_args);
764     CommandReturnObject result;
765     // Check to see if the command being aliased can take any command options.
766     Options *options = cmd_obj_sp->GetOptions ();
767     if (options)
768     {
769         // See if any options were specified as part of the alias;  if so, handle them appropriately.
770         options->NotifyOptionParsingStarting ();
771         args.Unshift ("dummy_arg");
772         args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
773         args.Shift ();
774         if (result.Succeeded())
775             options->VerifyPartialOptions (result);
776         if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
777         {
778             result.AppendError ("Unable to create requested alias.\n");
779             return false;
780         }
781     }
782 
783     if (!options_string.empty())
784     {
785         if (cmd_obj_sp->WantsRawCommandString ())
786             option_arg_vector->push_back (OptionArgPair ("<argument>",
787                                                           OptionArgValue (-1,
788                                                                           options_string)));
789         else
790         {
791             int argc = args.GetArgumentCount();
792             for (size_t i = 0; i < argc; ++i)
793                 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
794                     option_arg_vector->push_back
795                                 (OptionArgPair ("<argument>",
796                                                 OptionArgValue (-1,
797                                                                 std::string (args.GetArgumentAtIndex (i)))));
798         }
799     }
800 
801     return success;
802 }
803 
804 bool
805 CommandInterpreter::AliasExists (const char *cmd)
806 {
807     return m_alias_dict.find(cmd) != m_alias_dict.end();
808 }
809 
810 bool
811 CommandInterpreter::UserCommandExists (const char *cmd)
812 {
813     return m_user_dict.find(cmd) != m_user_dict.end();
814 }
815 
816 void
817 CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
818 {
819     command_obj_sp->SetIsAlias (true);
820     m_alias_dict[alias_name] = command_obj_sp;
821 }
822 
823 bool
824 CommandInterpreter::RemoveAlias (const char *alias_name)
825 {
826     CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
827     if (pos != m_alias_dict.end())
828     {
829         m_alias_dict.erase(pos);
830         return true;
831     }
832     return false;
833 }
834 bool
835 CommandInterpreter::RemoveUser (const char *alias_name)
836 {
837     CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
838     if (pos != m_user_dict.end())
839     {
840         m_user_dict.erase(pos);
841         return true;
842     }
843     return false;
844 }
845 
846 void
847 CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
848 {
849     help_string.Printf ("'%s", command_name);
850     OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
851 
852     if (option_arg_vector_sp)
853     {
854         OptionArgVector *options = option_arg_vector_sp.get();
855         for (int i = 0; i < options->size(); ++i)
856         {
857             OptionArgPair cur_option = (*options)[i];
858             std::string opt = cur_option.first;
859             OptionArgValue value_pair = cur_option.second;
860             std::string value = value_pair.second;
861             if (opt.compare("<argument>") == 0)
862             {
863                 help_string.Printf (" %s", value.c_str());
864             }
865             else
866             {
867                 help_string.Printf (" %s", opt.c_str());
868                 if ((value.compare ("<no-argument>") != 0)
869                     && (value.compare ("<need-argument") != 0))
870                 {
871                     help_string.Printf (" %s", value.c_str());
872                 }
873             }
874         }
875     }
876 
877     help_string.Printf ("'");
878 }
879 
880 size_t
881 CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
882 {
883     CommandObject::CommandMap::const_iterator pos;
884     CommandObject::CommandMap::const_iterator end = dict.end();
885     size_t max_len = 0;
886 
887     for (pos = dict.begin(); pos != end; ++pos)
888     {
889         size_t len = pos->first.size();
890         if (max_len < len)
891             max_len = len;
892     }
893     return max_len;
894 }
895 
896 void
897 CommandInterpreter::GetHelp (CommandReturnObject &result,
898                              uint32_t cmd_types)
899 {
900     CommandObject::CommandMap::const_iterator pos;
901     uint32_t max_len = FindLongestCommandWord (m_command_dict);
902 
903     if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
904     {
905 
906         result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
907         result.AppendMessage("");
908 
909         for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
910         {
911             OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
912                                      max_len);
913         }
914         result.AppendMessage("");
915 
916     }
917 
918     if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
919     {
920         result.AppendMessage("The following is a list of your current command abbreviations "
921                              "(see 'help command alias' for more info):");
922         result.AppendMessage("");
923         max_len = FindLongestCommandWord (m_alias_dict);
924 
925         for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
926         {
927             StreamString sstr;
928             StreamString translation_and_help;
929             std::string entry_name = pos->first;
930             std::string second_entry = pos->second.get()->GetCommandName();
931             GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
932 
933             translation_and_help.Printf ("(%s)  %s", sstr.GetData(), pos->second->GetHelp());
934             OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
935                                      translation_and_help.GetData(), max_len);
936         }
937         result.AppendMessage("");
938     }
939 
940     if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
941     {
942         result.AppendMessage ("The following is a list of your current user-defined commands:");
943         result.AppendMessage("");
944         max_len = FindLongestCommandWord (m_user_dict);
945         for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
946         {
947             OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
948                                      max_len);
949         }
950         result.AppendMessage("");
951     }
952 
953     result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
954 }
955 
956 CommandObject *
957 CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
958 {
959     // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
960     // eventually be invoked by the given command line.
961 
962     CommandObject *cmd_obj = NULL;
963     std::string white_space (" \t\v");
964     size_t start = command_string.find_first_not_of (white_space);
965     size_t end = 0;
966     bool done = false;
967     while (!done)
968     {
969         if (start != std::string::npos)
970         {
971             // Get the next word from command_string.
972             end = command_string.find_first_of (white_space, start);
973             if (end == std::string::npos)
974                 end = command_string.size();
975             std::string cmd_word = command_string.substr (start, end - start);
976 
977             if (cmd_obj == NULL)
978                 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
979                 // command or alias.
980                 cmd_obj = GetCommandObject (cmd_word.c_str());
981             else if (cmd_obj->IsMultiwordObject ())
982             {
983                 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
984                 CommandObject *sub_cmd_obj =
985                                          ((CommandObjectMultiword *) cmd_obj)->GetSubcommandObject (cmd_word.c_str());
986                 if (sub_cmd_obj)
987                     cmd_obj = sub_cmd_obj;
988                 else // cmd_word was not a valid sub-command word, so we are donee
989                     done = true;
990             }
991             else
992                 // We have a cmd_obj and it is not a multi-word object, so we are done.
993                 done = true;
994 
995             // If we didn't find a valid command object, or our command object is not a multi-word object, or
996             // we are at the end of the command_string, then we are done.  Otherwise, find the start of the
997             // next word.
998 
999             if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
1000                 done = true;
1001             else
1002                 start = command_string.find_first_not_of (white_space, end);
1003         }
1004         else
1005             // Unable to find any more words.
1006             done = true;
1007     }
1008 
1009     if (end == command_string.size())
1010         command_string.clear();
1011     else
1012         command_string = command_string.substr(end);
1013 
1014     return cmd_obj;
1015 }
1016 
1017 static const char *k_white_space = " \t\v";
1018 static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1019 static void
1020 StripLeadingSpaces (std::string &s)
1021 {
1022     if (!s.empty())
1023     {
1024         size_t pos = s.find_first_not_of (k_white_space);
1025         if (pos == std::string::npos)
1026             s.clear();
1027         else if (pos == 0)
1028             return;
1029         s.erase (0, pos);
1030     }
1031 }
1032 
1033 static size_t
1034 FindArgumentTerminator (const std::string &s)
1035 {
1036     const size_t s_len = s.size();
1037     size_t offset = 0;
1038     while (offset < s_len)
1039     {
1040         size_t pos = s.find ("--", offset);
1041         if (pos == std::string::npos)
1042             break;
1043         if (pos > 0)
1044         {
1045             if (isspace(s[pos-1]))
1046             {
1047                 // Check if the string ends "\s--" (where \s is a space character)
1048                 // or if we have "\s--\s".
1049                 if ((pos + 2 >= s_len) || isspace(s[pos+2]))
1050                 {
1051                     return pos;
1052                 }
1053             }
1054         }
1055         offset = pos + 2;
1056     }
1057     return std::string::npos;
1058 }
1059 
1060 static bool
1061 ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char &quote_char)
1062 {
1063     command.clear();
1064     suffix.clear();
1065     StripLeadingSpaces (command_string);
1066 
1067     bool result = false;
1068     quote_char = '\0';
1069 
1070     if (!command_string.empty())
1071     {
1072         const char first_char = command_string[0];
1073         if (first_char == '\'' || first_char == '"')
1074         {
1075             quote_char = first_char;
1076             const size_t end_quote_pos = command_string.find (quote_char, 1);
1077             if (end_quote_pos == std::string::npos)
1078             {
1079                 command.swap (command_string);
1080                 command_string.erase ();
1081             }
1082             else
1083             {
1084                 command.assign (command_string, 1, end_quote_pos - 1);
1085                 if (end_quote_pos + 1 < command_string.size())
1086                     command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
1087                 else
1088                     command_string.erase ();
1089             }
1090         }
1091         else
1092         {
1093             const size_t first_space_pos = command_string.find_first_of (k_white_space);
1094             if (first_space_pos == std::string::npos)
1095             {
1096                 command.swap (command_string);
1097                 command_string.erase();
1098             }
1099             else
1100             {
1101                 command.assign (command_string, 0, first_space_pos);
1102                 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
1103             }
1104         }
1105         result = true;
1106     }
1107 
1108 
1109     if (!command.empty())
1110     {
1111         // actual commands can't start with '-' or '_'
1112         if (command[0] != '-' && command[0] != '_')
1113         {
1114             size_t pos = command.find_first_not_of(k_valid_command_chars);
1115             if (pos > 0 && pos != std::string::npos)
1116             {
1117                 suffix.assign (command.begin() + pos, command.end());
1118                 command.erase (pos);
1119             }
1120         }
1121     }
1122 
1123     return result;
1124 }
1125 
1126 CommandObject *
1127 CommandInterpreter::BuildAliasResult (const char *alias_name,
1128                                       std::string &raw_input_string,
1129                                       std::string &alias_result,
1130                                       CommandReturnObject &result)
1131 {
1132     CommandObject *alias_cmd_obj = NULL;
1133     Args cmd_args (raw_input_string.c_str());
1134     alias_cmd_obj = GetCommandObject (alias_name);
1135     StreamString result_str;
1136 
1137     if (alias_cmd_obj)
1138     {
1139         std::string alias_name_str = alias_name;
1140         if ((cmd_args.GetArgumentCount() == 0)
1141             || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
1142             cmd_args.Unshift (alias_name);
1143 
1144         result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
1145         OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1146 
1147         if (option_arg_vector_sp.get())
1148         {
1149             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1150 
1151             for (int i = 0; i < option_arg_vector->size(); ++i)
1152             {
1153                 OptionArgPair option_pair = (*option_arg_vector)[i];
1154                 OptionArgValue value_pair = option_pair.second;
1155                 int value_type = value_pair.first;
1156                 std::string option = option_pair.first;
1157                 std::string value = value_pair.second;
1158                 if (option.compare ("<argument>") == 0)
1159                     result_str.Printf (" %s", value.c_str());
1160                 else
1161                 {
1162                     result_str.Printf (" %s", option.c_str());
1163                     if (value_type != optional_argument)
1164                         result_str.Printf (" ");
1165                     if (value.compare ("<no_argument>") != 0)
1166                     {
1167                         int index = GetOptionArgumentPosition (value.c_str());
1168                         if (index == 0)
1169                             result_str.Printf ("%s", value.c_str());
1170                         else if (index >= cmd_args.GetArgumentCount())
1171                         {
1172 
1173                             result.AppendErrorWithFormat
1174                             ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
1175                              index);
1176                             result.SetStatus (eReturnStatusFailed);
1177                             return alias_cmd_obj;
1178                         }
1179                         else
1180                         {
1181                             size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
1182                             if (strpos != std::string::npos)
1183                                 raw_input_string = raw_input_string.erase (strpos,
1184                                                                           strlen (cmd_args.GetArgumentAtIndex (index)));
1185                             result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
1186                         }
1187                     }
1188                 }
1189             }
1190         }
1191 
1192         alias_result = result_str.GetData();
1193     }
1194     return alias_cmd_obj;
1195 }
1196 
1197 Error
1198 CommandInterpreter::PreprocessCommand (std::string &command)
1199 {
1200     // The command preprocessor needs to do things to the command
1201     // line before any parsing of arguments or anything else is done.
1202     // The only current stuff that gets proprocessed is anyting enclosed
1203     // in backtick ('`') characters is evaluated as an expression and
1204     // the result of the expression must be a scalar that can be substituted
1205     // into the command. An example would be:
1206     // (lldb) memory read `$rsp + 20`
1207     Error error; // Error for any expressions that might not evaluate
1208     size_t start_backtick;
1209     size_t pos = 0;
1210     while ((start_backtick = command.find ('`', pos)) != std::string::npos)
1211     {
1212         if (start_backtick > 0 && command[start_backtick-1] == '\\')
1213         {
1214             // The backtick was preceeded by a '\' character, remove the slash
1215             // and don't treat the backtick as the start of an expression
1216             command.erase(start_backtick-1, 1);
1217             // No need to add one to start_backtick since we just deleted a char
1218             pos = start_backtick;
1219         }
1220         else
1221         {
1222             const size_t expr_content_start = start_backtick + 1;
1223             const size_t end_backtick = command.find ('`', expr_content_start);
1224             if (end_backtick == std::string::npos)
1225                 return error;
1226             else if (end_backtick == expr_content_start)
1227             {
1228                 // Empty expression (two backticks in a row)
1229                 command.erase (start_backtick, 2);
1230             }
1231             else
1232             {
1233                 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
1234 
1235                 ExecutionContext exe_ctx(GetExecutionContext());
1236                 Target *target = exe_ctx.GetTargetPtr();
1237                 // Get a dummy target to allow for calculator mode while processing backticks.
1238                 // This also helps break the infinite loop caused when target is null.
1239                 if (!target)
1240                     target = Host::GetDummyTarget(GetDebugger()).get();
1241                 if (target)
1242                 {
1243                     ValueObjectSP expr_result_valobj_sp;
1244 
1245                     Target::EvaluateExpressionOptions options;
1246                     options.SetCoerceToId(false)
1247                     .SetUnwindOnError(true)
1248                     .SetKeepInMemory(false)
1249                     .SetSingleThreadTimeoutUsec(0);
1250 
1251                     ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
1252                                                                                exe_ctx.GetFramePtr(),
1253                                                                                expr_result_valobj_sp,
1254                                                                                options);
1255 
1256                     if (expr_result == eExecutionCompleted)
1257                     {
1258                         Scalar scalar;
1259                         if (expr_result_valobj_sp->ResolveValue (scalar))
1260                         {
1261                             command.erase (start_backtick, end_backtick - start_backtick + 1);
1262                             StreamString value_strm;
1263                             const bool show_type = false;
1264                             scalar.GetValue (&value_strm, show_type);
1265                             size_t value_string_size = value_strm.GetSize();
1266                             if (value_string_size)
1267                             {
1268                                 command.insert (start_backtick, value_strm.GetData(), value_string_size);
1269                                 pos = start_backtick + value_string_size;
1270                                 continue;
1271                             }
1272                             else
1273                             {
1274                                 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1275                             }
1276                         }
1277                         else
1278                         {
1279                             error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1280                         }
1281                     }
1282                     else
1283                     {
1284                         if (expr_result_valobj_sp)
1285                             error = expr_result_valobj_sp->GetError();
1286                         if (error.Success())
1287                         {
1288 
1289                             switch (expr_result)
1290                             {
1291                                 case eExecutionSetupError:
1292                                     error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
1293                                     break;
1294                                 case eExecutionCompleted:
1295                                     break;
1296                                 case eExecutionDiscarded:
1297                                     error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
1298                                     break;
1299                                 case eExecutionInterrupted:
1300                                     error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
1301                                     break;
1302                                 case eExecutionTimedOut:
1303                                     error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
1304                                     break;
1305                             }
1306                         }
1307                     }
1308                 }
1309             }
1310             if (error.Fail())
1311                 break;
1312         }
1313     }
1314     return error;
1315 }
1316 
1317 
1318 bool
1319 CommandInterpreter::HandleCommand (const char *command_line,
1320                                    LazyBool lazy_add_to_history,
1321                                    CommandReturnObject &result,
1322                                    ExecutionContext *override_context,
1323                                    bool repeat_on_empty_command,
1324                                    bool no_context_switching)
1325 
1326 {
1327 
1328     bool done = false;
1329     CommandObject *cmd_obj = NULL;
1330     bool wants_raw_input = false;
1331     std::string command_string (command_line);
1332     std::string original_command_string (command_line);
1333 
1334     LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
1335     Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
1336 
1337     // Make a scoped cleanup object that will clear the crash description string
1338     // on exit of this function.
1339     lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription);
1340 
1341     if (log)
1342         log->Printf ("Processing command: %s", command_line);
1343 
1344     Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
1345 
1346     if (!no_context_switching)
1347         UpdateExecutionContext (override_context);
1348 
1349     // <rdar://problem/11328896>
1350     bool add_to_history;
1351     if (lazy_add_to_history == eLazyBoolCalculate)
1352         add_to_history = (m_command_source_depth == 0);
1353     else
1354         add_to_history = (lazy_add_to_history == eLazyBoolYes);
1355 
1356     bool empty_command = false;
1357     bool comment_command = false;
1358     if (command_string.empty())
1359         empty_command = true;
1360     else
1361     {
1362         const char *k_space_characters = "\t\n\v\f\r ";
1363 
1364         size_t non_space = command_string.find_first_not_of (k_space_characters);
1365         // Check for empty line or comment line (lines whose first
1366         // non-space character is the comment character for this interpreter)
1367         if (non_space == std::string::npos)
1368             empty_command = true;
1369         else if (command_string[non_space] == m_comment_char)
1370              comment_command = true;
1371         else if (command_string[non_space] == m_repeat_char)
1372         {
1373             const char *history_string = FindHistoryString (command_string.c_str() + non_space);
1374             if (history_string == NULL)
1375             {
1376                 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
1377                 result.SetStatus(eReturnStatusFailed);
1378                 return false;
1379             }
1380             add_to_history = false;
1381             command_string = history_string;
1382             original_command_string = history_string;
1383         }
1384     }
1385 
1386     if (empty_command)
1387     {
1388         if (repeat_on_empty_command)
1389         {
1390             if (m_command_history.empty())
1391             {
1392                 result.AppendError ("empty command");
1393                 result.SetStatus(eReturnStatusFailed);
1394                 return false;
1395             }
1396             else
1397             {
1398                 command_line = m_repeat_command.c_str();
1399                 command_string = command_line;
1400                 original_command_string = command_line;
1401                 if (m_repeat_command.empty())
1402                 {
1403                     result.AppendErrorWithFormat("No auto repeat.\n");
1404                     result.SetStatus (eReturnStatusFailed);
1405                     return false;
1406                 }
1407             }
1408             add_to_history = false;
1409         }
1410         else
1411         {
1412             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1413             return true;
1414         }
1415     }
1416     else if (comment_command)
1417     {
1418         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1419         return true;
1420     }
1421 
1422 
1423     Error error (PreprocessCommand (command_string));
1424 
1425     if (error.Fail())
1426     {
1427         result.AppendError (error.AsCString());
1428         result.SetStatus(eReturnStatusFailed);
1429         return false;
1430     }
1431     // Phase 1.
1432 
1433     // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
1434     // is for the specified command, and whether or not it wants raw input.  This gets complicated by the fact that
1435     // the user could have specified an alias, and in translating the alias there may also be command options and/or
1436     // even data (including raw text strings) that need to be found and inserted into the command line as part of
1437     // the translation.  So this first step is plain look-up & replacement, resulting in three things:  1). the command
1438     // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
1439     // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
1440 
1441     StreamString revised_command_line;
1442     size_t actual_cmd_name_len = 0;
1443     std::string next_word;
1444     StringList matches;
1445     while (!done)
1446     {
1447         char quote_char = '\0';
1448         std::string suffix;
1449         ExtractCommand (command_string, next_word, suffix, quote_char);
1450         if (cmd_obj == NULL)
1451         {
1452             if (AliasExists (next_word.c_str()))
1453             {
1454                 std::string alias_result;
1455                 cmd_obj = BuildAliasResult (next_word.c_str(), command_string, alias_result, result);
1456                 revised_command_line.Printf ("%s", alias_result.c_str());
1457                 if (cmd_obj)
1458                 {
1459                     wants_raw_input = cmd_obj->WantsRawCommandString ();
1460                     actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
1461                 }
1462             }
1463             else
1464             {
1465                 cmd_obj = GetCommandObject (next_word.c_str(), &matches);
1466                 if (cmd_obj)
1467                 {
1468                     actual_cmd_name_len += next_word.length();
1469                     revised_command_line.Printf ("%s", next_word.c_str());
1470                     wants_raw_input = cmd_obj->WantsRawCommandString ();
1471                 }
1472                 else
1473                 {
1474                     revised_command_line.Printf ("%s", next_word.c_str());
1475                 }
1476             }
1477         }
1478         else
1479         {
1480             if (cmd_obj->IsMultiwordObject ())
1481             {
1482                 CommandObject *sub_cmd_obj = ((CommandObjectMultiword *) cmd_obj)->GetSubcommandObject (next_word.c_str());
1483                 if (sub_cmd_obj)
1484                 {
1485                     actual_cmd_name_len += next_word.length() + 1;
1486                     revised_command_line.Printf (" %s", next_word.c_str());
1487                     cmd_obj = sub_cmd_obj;
1488                     wants_raw_input = cmd_obj->WantsRawCommandString ();
1489                 }
1490                 else
1491                 {
1492                     if (quote_char)
1493                         revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1494                     else
1495                         revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1496                     done = true;
1497                 }
1498             }
1499             else
1500             {
1501                 if (quote_char)
1502                     revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1503                 else
1504                     revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1505                 done = true;
1506             }
1507         }
1508 
1509         if (cmd_obj == NULL)
1510         {
1511             uint32_t num_matches = matches.GetSize();
1512             if (matches.GetSize() > 1) {
1513                 std::string error_msg;
1514                 error_msg.assign ("Ambiguous command '");
1515                 error_msg.append(next_word.c_str());
1516                 error_msg.append ("'.");
1517 
1518                 error_msg.append (" Possible matches:");
1519 
1520                 for (uint32_t i = 0; i < num_matches; ++i) {
1521                     error_msg.append ("\n\t");
1522                     error_msg.append (matches.GetStringAtIndex(i));
1523                 }
1524                 error_msg.append ("\n");
1525                 result.AppendRawError (error_msg.c_str(), error_msg.size());
1526             } else {
1527                 // We didn't have only one match, otherwise we wouldn't get here.
1528                 assert(num_matches == 0);
1529                 result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
1530             }
1531             result.SetStatus (eReturnStatusFailed);
1532             return false;
1533         }
1534 
1535         if (cmd_obj->IsMultiwordObject ())
1536         {
1537             if (!suffix.empty())
1538             {
1539 
1540                 result.AppendErrorWithFormat ("multi-word commands ('%s') can't have shorthand suffixes: '%s'\n",
1541                                               next_word.c_str(),
1542                                               suffix.c_str());
1543                 result.SetStatus (eReturnStatusFailed);
1544                 return false;
1545             }
1546         }
1547         else
1548         {
1549             // If we found a normal command, we are done
1550             done = true;
1551             if (!suffix.empty())
1552             {
1553                 switch (suffix[0])
1554                 {
1555                 case '/':
1556                     // GDB format suffixes
1557                     {
1558                         Options *command_options = cmd_obj->GetOptions();
1559                         if (command_options && command_options->SupportsLongOption("gdb-format"))
1560                         {
1561                             std::string gdb_format_option ("--gdb-format=");
1562                             gdb_format_option += (suffix.c_str() + 1);
1563 
1564                             bool inserted = false;
1565                             std::string &cmd = revised_command_line.GetString();
1566                             size_t arg_terminator_idx = FindArgumentTerminator (cmd);
1567                             if (arg_terminator_idx != std::string::npos)
1568                             {
1569                                 // Insert the gdb format option before the "--" that terminates options
1570                                 gdb_format_option.append(1,' ');
1571                                 cmd.insert(arg_terminator_idx, gdb_format_option);
1572                                 inserted = true;
1573                             }
1574 
1575                             if (!inserted)
1576                                 revised_command_line.Printf (" %s", gdb_format_option.c_str());
1577 
1578                             if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
1579                                 revised_command_line.PutCString (" --");
1580                         }
1581                         else
1582                         {
1583                             result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n",
1584                                                           cmd_obj->GetCommandName());
1585                             result.SetStatus (eReturnStatusFailed);
1586                             return false;
1587                         }
1588                     }
1589                     break;
1590 
1591                 default:
1592                     result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n",
1593                                                   suffix.c_str());
1594                     result.SetStatus (eReturnStatusFailed);
1595                     return false;
1596 
1597                 }
1598             }
1599         }
1600         if (command_string.length() == 0)
1601             done = true;
1602 
1603     }
1604 
1605     if (!command_string.empty())
1606         revised_command_line.Printf (" %s", command_string.c_str());
1607 
1608     // End of Phase 1.
1609     // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
1610     // specified was valid; revised_command_line contains the complete command line (including command name(s)),
1611     // fully translated with all substitutions & translations taken care of (still in raw text format); and
1612     // wants_raw_input specifies whether the Execute method expects raw input or not.
1613 
1614 
1615     if (log)
1616     {
1617         log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
1618         log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
1619         log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
1620     }
1621 
1622     // Phase 2.
1623     // Take care of things like setting up the history command & calling the appropriate Execute method on the
1624     // CommandObject, with the appropriate arguments.
1625 
1626     if (cmd_obj != NULL)
1627     {
1628         if (add_to_history)
1629         {
1630             Args command_args (revised_command_line.GetData());
1631             const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
1632             if (repeat_command != NULL)
1633                 m_repeat_command.assign(repeat_command);
1634             else
1635                 m_repeat_command.assign(original_command_string.c_str());
1636 
1637             // Don't keep pushing the same command onto the history...
1638             if (m_command_history.empty() || m_command_history.back() != original_command_string)
1639                 m_command_history.push_back (original_command_string);
1640         }
1641 
1642         command_string = revised_command_line.GetData();
1643         std::string command_name (cmd_obj->GetCommandName());
1644         std::string remainder;
1645         if (actual_cmd_name_len < command_string.length())
1646             remainder = command_string.substr (actual_cmd_name_len);  // Note: 'actual_cmd_name_len' may be considerably shorter
1647                                                            // than cmd_obj->GetCommandName(), because name completion
1648                                                            // allows users to enter short versions of the names,
1649                                                            // e.g. 'br s' for 'breakpoint set'.
1650 
1651         // Remove any initial spaces
1652         std::string white_space (" \t\v");
1653         size_t pos = remainder.find_first_not_of (white_space);
1654         if (pos != 0 && pos != std::string::npos)
1655             remainder.erase(0, pos);
1656 
1657         if (log)
1658             log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
1659 
1660         cmd_obj->Execute (remainder.c_str(), result);
1661     }
1662     else
1663     {
1664         // We didn't find the first command object, so complete the first argument.
1665         Args command_args (revised_command_line.GetData());
1666         StringList matches;
1667         int num_matches;
1668         int cursor_index = 0;
1669         int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
1670         bool word_complete;
1671         num_matches = HandleCompletionMatches (command_args,
1672                                                cursor_index,
1673                                                cursor_char_position,
1674                                                0,
1675                                                -1,
1676                                                word_complete,
1677                                                matches);
1678 
1679         if (num_matches > 0)
1680         {
1681             std::string error_msg;
1682             error_msg.assign ("ambiguous command '");
1683             error_msg.append(command_args.GetArgumentAtIndex(0));
1684             error_msg.append ("'.");
1685 
1686             error_msg.append (" Possible completions:");
1687             for (int i = 0; i < num_matches; i++)
1688             {
1689                 error_msg.append ("\n\t");
1690                 error_msg.append (matches.GetStringAtIndex (i));
1691             }
1692             error_msg.append ("\n");
1693             result.AppendRawError (error_msg.c_str(), error_msg.size());
1694         }
1695         else
1696             result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
1697 
1698         result.SetStatus (eReturnStatusFailed);
1699     }
1700 
1701     if (log)
1702       log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
1703 
1704     return result.Succeeded();
1705 }
1706 
1707 int
1708 CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
1709                                              int &cursor_index,
1710                                              int &cursor_char_position,
1711                                              int match_start_point,
1712                                              int max_return_elements,
1713                                              bool &word_complete,
1714                                              StringList &matches)
1715 {
1716     int num_command_matches = 0;
1717     bool look_for_subcommand = false;
1718 
1719     // For any of the command completions a unique match will be a complete word.
1720     word_complete = true;
1721 
1722     if (cursor_index == -1)
1723     {
1724         // We got nothing on the command line, so return the list of commands
1725         bool include_aliases = true;
1726         num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
1727     }
1728     else if (cursor_index == 0)
1729     {
1730         // The cursor is in the first argument, so just do a lookup in the dictionary.
1731         CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
1732         num_command_matches = matches.GetSize();
1733 
1734         if (num_command_matches == 1
1735             && cmd_obj && cmd_obj->IsMultiwordObject()
1736             && matches.GetStringAtIndex(0) != NULL
1737             && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
1738         {
1739             look_for_subcommand = true;
1740             num_command_matches = 0;
1741             matches.DeleteStringAtIndex(0);
1742             parsed_line.AppendArgument ("");
1743             cursor_index++;
1744             cursor_char_position = 0;
1745         }
1746     }
1747 
1748     if (cursor_index > 0 || look_for_subcommand)
1749     {
1750         // We are completing further on into a commands arguments, so find the command and tell it
1751         // to complete the command.
1752         // First see if there is a matching initial command:
1753         CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
1754         if (command_object == NULL)
1755         {
1756             return 0;
1757         }
1758         else
1759         {
1760             parsed_line.Shift();
1761             cursor_index--;
1762             num_command_matches = command_object->HandleCompletion (parsed_line,
1763                                                                     cursor_index,
1764                                                                     cursor_char_position,
1765                                                                     match_start_point,
1766                                                                     max_return_elements,
1767                                                                     word_complete,
1768                                                                     matches);
1769         }
1770     }
1771 
1772     return num_command_matches;
1773 
1774 }
1775 
1776 int
1777 CommandInterpreter::HandleCompletion (const char *current_line,
1778                                       const char *cursor,
1779                                       const char *last_char,
1780                                       int match_start_point,
1781                                       int max_return_elements,
1782                                       StringList &matches)
1783 {
1784     // We parse the argument up to the cursor, so the last argument in parsed_line is
1785     // the one containing the cursor, and the cursor is after the last character.
1786 
1787     Args parsed_line(current_line, last_char - current_line);
1788     Args partial_parsed_line(current_line, cursor - current_line);
1789 
1790     // Don't complete comments, and if the line we are completing is just the history repeat character,
1791     // substitute the appropriate history line.
1792     const char *first_arg = parsed_line.GetArgumentAtIndex(0);
1793     if (first_arg)
1794     {
1795         if (first_arg[0] == m_comment_char)
1796             return 0;
1797         else if (first_arg[0] == m_repeat_char)
1798         {
1799             const char *history_string = FindHistoryString (first_arg);
1800             if (history_string != NULL)
1801             {
1802                 matches.Clear();
1803                 matches.InsertStringAtIndex(0, history_string);
1804                 return -2;
1805             }
1806             else
1807                 return 0;
1808 
1809         }
1810     }
1811 
1812 
1813     int num_args = partial_parsed_line.GetArgumentCount();
1814     int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
1815     int cursor_char_position;
1816 
1817     if (cursor_index == -1)
1818         cursor_char_position = 0;
1819     else
1820         cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
1821 
1822     if (cursor > current_line && cursor[-1] == ' ')
1823     {
1824         // We are just after a space.  If we are in an argument, then we will continue
1825         // parsing, but if we are between arguments, then we have to complete whatever the next
1826         // element would be.
1827         // We can distinguish the two cases because if we are in an argument (e.g. because the space is
1828         // protected by a quote) then the space will also be in the parsed argument...
1829 
1830         const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
1831         if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
1832         {
1833             parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '"');
1834             cursor_index++;
1835             cursor_char_position = 0;
1836         }
1837     }
1838 
1839     int num_command_matches;
1840 
1841     matches.Clear();
1842 
1843     // Only max_return_elements == -1 is supported at present:
1844     assert (max_return_elements == -1);
1845     bool word_complete;
1846     num_command_matches = HandleCompletionMatches (parsed_line,
1847                                                    cursor_index,
1848                                                    cursor_char_position,
1849                                                    match_start_point,
1850                                                    max_return_elements,
1851                                                    word_complete,
1852                                                    matches);
1853 
1854     if (num_command_matches <= 0)
1855             return num_command_matches;
1856 
1857     if (num_args == 0)
1858     {
1859         // If we got an empty string, insert nothing.
1860         matches.InsertStringAtIndex(0, "");
1861     }
1862     else
1863     {
1864         // Now figure out if there is a common substring, and if so put that in element 0, otherwise
1865         // put an empty string in element 0.
1866         std::string command_partial_str;
1867         if (cursor_index >= 0)
1868             command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
1869                                        parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
1870 
1871         std::string common_prefix;
1872         matches.LongestCommonPrefix (common_prefix);
1873         int partial_name_len = command_partial_str.size();
1874 
1875         // If we matched a unique single command, add a space...
1876         // Only do this if the completer told us this was a complete word, however...
1877         if (num_command_matches == 1 && word_complete)
1878         {
1879             char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
1880             if (quote_char != '\0')
1881                 common_prefix.push_back(quote_char);
1882 
1883             common_prefix.push_back(' ');
1884         }
1885         common_prefix.erase (0, partial_name_len);
1886         matches.InsertStringAtIndex(0, common_prefix.c_str());
1887     }
1888     return num_command_matches;
1889 }
1890 
1891 
1892 CommandInterpreter::~CommandInterpreter ()
1893 {
1894 }
1895 
1896 const char *
1897 CommandInterpreter::GetPrompt ()
1898 {
1899     return m_debugger.GetPrompt();
1900 }
1901 
1902 void
1903 CommandInterpreter::SetPrompt (const char *new_prompt)
1904 {
1905     m_debugger.SetPrompt (new_prompt);
1906 }
1907 
1908 size_t
1909 CommandInterpreter::GetConfirmationInputReaderCallback
1910 (
1911     void *baton,
1912     InputReader &reader,
1913     lldb::InputReaderAction action,
1914     const char *bytes,
1915     size_t bytes_len
1916 )
1917 {
1918     File &out_file = reader.GetDebugger().GetOutputFile();
1919     bool *response_ptr = (bool *) baton;
1920 
1921     switch (action)
1922     {
1923     case eInputReaderActivate:
1924         if (out_file.IsValid())
1925         {
1926             if (reader.GetPrompt())
1927             {
1928                 out_file.Printf ("%s", reader.GetPrompt());
1929                 out_file.Flush ();
1930             }
1931         }
1932         break;
1933 
1934     case eInputReaderDeactivate:
1935         break;
1936 
1937     case eInputReaderReactivate:
1938         if (out_file.IsValid() && reader.GetPrompt())
1939         {
1940             out_file.Printf ("%s", reader.GetPrompt());
1941             out_file.Flush ();
1942         }
1943         break;
1944 
1945     case eInputReaderAsynchronousOutputWritten:
1946         break;
1947 
1948     case eInputReaderGotToken:
1949         if (bytes_len == 0)
1950         {
1951             reader.SetIsDone(true);
1952         }
1953         else if (bytes[0] == 'y' || bytes[0] == 'Y')
1954         {
1955             *response_ptr = true;
1956             reader.SetIsDone(true);
1957         }
1958         else if (bytes[0] == 'n' || bytes[0] == 'N')
1959         {
1960             *response_ptr = false;
1961             reader.SetIsDone(true);
1962         }
1963         else
1964         {
1965             if (out_file.IsValid() && !reader.IsDone() && reader.GetPrompt())
1966             {
1967                 out_file.Printf ("Please answer \"y\" or \"n\".\n%s", reader.GetPrompt());
1968                 out_file.Flush ();
1969             }
1970         }
1971         break;
1972 
1973     case eInputReaderInterrupt:
1974     case eInputReaderEndOfFile:
1975         *response_ptr = false;  // Assume ^C or ^D means cancel the proposed action
1976         reader.SetIsDone (true);
1977         break;
1978 
1979     case eInputReaderDone:
1980         break;
1981     }
1982 
1983     return bytes_len;
1984 
1985 }
1986 
1987 bool
1988 CommandInterpreter::Confirm (const char *message, bool default_answer)
1989 {
1990     // Check AutoConfirm first:
1991     if (m_debugger.GetAutoConfirm())
1992         return default_answer;
1993 
1994     InputReaderSP reader_sp (new InputReader(GetDebugger()));
1995     bool response = default_answer;
1996     if (reader_sp)
1997     {
1998         std::string prompt(message);
1999         prompt.append(": [");
2000         if (default_answer)
2001             prompt.append ("Y/n] ");
2002         else
2003             prompt.append ("y/N] ");
2004 
2005         Error err (reader_sp->Initialize (CommandInterpreter::GetConfirmationInputReaderCallback,
2006                                           &response,                    // baton
2007                                           eInputReaderGranularityLine,  // token size, to pass to callback function
2008                                           NULL,                         // end token
2009                                           prompt.c_str(),               // prompt
2010                                           true));                       // echo input
2011         if (err.Success())
2012         {
2013             GetDebugger().PushInputReader (reader_sp);
2014         }
2015         reader_sp->WaitOnReaderIsDone();
2016     }
2017     return response;
2018 }
2019 
2020 
2021 void
2022 CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
2023 {
2024     CommandObjectSP cmd_obj_sp = GetCommandSPExact (dest_cmd, true);
2025 
2026     if (cmd_obj_sp)
2027     {
2028         CommandObject *cmd_obj = cmd_obj_sp.get();
2029         if (cmd_obj->IsCrossRefObject ())
2030             cmd_obj->AddObject (object_type);
2031     }
2032 }
2033 
2034 OptionArgVectorSP
2035 CommandInterpreter::GetAliasOptions (const char *alias_name)
2036 {
2037     OptionArgMap::iterator pos;
2038     OptionArgVectorSP ret_val;
2039 
2040     std::string alias (alias_name);
2041 
2042     if (HasAliasOptions())
2043     {
2044         pos = m_alias_options.find (alias);
2045         if (pos != m_alias_options.end())
2046           ret_val = pos->second;
2047     }
2048 
2049     return ret_val;
2050 }
2051 
2052 void
2053 CommandInterpreter::RemoveAliasOptions (const char *alias_name)
2054 {
2055     OptionArgMap::iterator pos = m_alias_options.find(alias_name);
2056     if (pos != m_alias_options.end())
2057     {
2058         m_alias_options.erase (pos);
2059     }
2060 }
2061 
2062 void
2063 CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
2064 {
2065     m_alias_options[alias_name] = option_arg_vector_sp;
2066 }
2067 
2068 bool
2069 CommandInterpreter::HasCommands ()
2070 {
2071     return (!m_command_dict.empty());
2072 }
2073 
2074 bool
2075 CommandInterpreter::HasAliases ()
2076 {
2077     return (!m_alias_dict.empty());
2078 }
2079 
2080 bool
2081 CommandInterpreter::HasUserCommands ()
2082 {
2083     return (!m_user_dict.empty());
2084 }
2085 
2086 bool
2087 CommandInterpreter::HasAliasOptions ()
2088 {
2089     return (!m_alias_options.empty());
2090 }
2091 
2092 void
2093 CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
2094                                            const char *alias_name,
2095                                            Args &cmd_args,
2096                                            std::string &raw_input_string,
2097                                            CommandReturnObject &result)
2098 {
2099     OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
2100 
2101     bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
2102 
2103     // Make sure that the alias name is the 0th element in cmd_args
2104     std::string alias_name_str = alias_name;
2105     if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
2106         cmd_args.Unshift (alias_name);
2107 
2108     Args new_args (alias_cmd_obj->GetCommandName());
2109     if (new_args.GetArgumentCount() == 2)
2110         new_args.Shift();
2111 
2112     if (option_arg_vector_sp.get())
2113     {
2114         if (wants_raw_input)
2115         {
2116             // We have a command that both has command options and takes raw input.  Make *sure* it has a
2117             // " -- " in the right place in the raw_input_string.
2118             size_t pos = raw_input_string.find(" -- ");
2119             if (pos == std::string::npos)
2120             {
2121                 // None found; assume it goes at the beginning of the raw input string
2122                 raw_input_string.insert (0, " -- ");
2123             }
2124         }
2125 
2126         OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
2127         int old_size = cmd_args.GetArgumentCount();
2128         std::vector<bool> used (old_size + 1, false);
2129 
2130         used[0] = true;
2131 
2132         for (int i = 0; i < option_arg_vector->size(); ++i)
2133         {
2134             OptionArgPair option_pair = (*option_arg_vector)[i];
2135             OptionArgValue value_pair = option_pair.second;
2136             int value_type = value_pair.first;
2137             std::string option = option_pair.first;
2138             std::string value = value_pair.second;
2139             if (option.compare ("<argument>") == 0)
2140             {
2141                 if (!wants_raw_input
2142                     || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
2143                     new_args.AppendArgument (value.c_str());
2144             }
2145             else
2146             {
2147                 if (value_type != optional_argument)
2148                     new_args.AppendArgument (option.c_str());
2149                 if (value.compare ("<no-argument>") != 0)
2150                 {
2151                     int index = GetOptionArgumentPosition (value.c_str());
2152                     if (index == 0)
2153                     {
2154                         // value was NOT a positional argument; must be a real value
2155                         if (value_type != optional_argument)
2156                             new_args.AppendArgument (value.c_str());
2157                         else
2158                         {
2159                             char buffer[255];
2160                             ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
2161                             new_args.AppendArgument (buffer);
2162                         }
2163 
2164                     }
2165                     else if (index >= cmd_args.GetArgumentCount())
2166                     {
2167                         result.AppendErrorWithFormat
2168                                     ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
2169                                      index);
2170                         result.SetStatus (eReturnStatusFailed);
2171                         return;
2172                     }
2173                     else
2174                     {
2175                         // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2176                         size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
2177                         if (strpos != std::string::npos)
2178                         {
2179                             raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
2180                         }
2181 
2182                         if (value_type != optional_argument)
2183                             new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
2184                         else
2185                         {
2186                             char buffer[255];
2187                             ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
2188                                         cmd_args.GetArgumentAtIndex (index));
2189                             new_args.AppendArgument (buffer);
2190                         }
2191                         used[index] = true;
2192                     }
2193                 }
2194             }
2195         }
2196 
2197         for (int j = 0; j < cmd_args.GetArgumentCount(); ++j)
2198         {
2199             if (!used[j] && !wants_raw_input)
2200                 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
2201         }
2202 
2203         cmd_args.Clear();
2204         cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2205     }
2206     else
2207     {
2208         result.SetStatus (eReturnStatusSuccessFinishNoResult);
2209         // This alias was not created with any options; nothing further needs to be done, unless it is a command that
2210         // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
2211         // input string.
2212         if (wants_raw_input)
2213         {
2214             cmd_args.Clear();
2215             cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2216         }
2217         return;
2218     }
2219 
2220     result.SetStatus (eReturnStatusSuccessFinishNoResult);
2221     return;
2222 }
2223 
2224 
2225 int
2226 CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
2227 {
2228     int position = 0;   // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
2229                         // of zero.
2230 
2231     char *cptr = (char *) in_string;
2232 
2233     // Does it start with '%'
2234     if (cptr[0] == '%')
2235     {
2236         ++cptr;
2237 
2238         // Is the rest of it entirely digits?
2239         if (isdigit (cptr[0]))
2240         {
2241             const char *start = cptr;
2242             while (isdigit (cptr[0]))
2243                 ++cptr;
2244 
2245             // We've gotten to the end of the digits; are we at the end of the string?
2246             if (cptr[0] == '\0')
2247                 position = atoi (start);
2248         }
2249     }
2250 
2251     return position;
2252 }
2253 
2254 void
2255 CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
2256 {
2257     FileSpec init_file;
2258     if (in_cwd)
2259     {
2260         // In the current working directory we don't load any program specific
2261         // .lldbinit files, we only look for a "./.lldbinit" file.
2262         if (m_skip_lldbinit_files)
2263             return;
2264 
2265         init_file.SetFile ("./.lldbinit", true);
2266     }
2267     else
2268     {
2269         // If we aren't looking in the current working directory we are looking
2270         // in the home directory. We will first see if there is an application
2271         // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
2272         // "-" and the name of the program. If this file doesn't exist, we fall
2273         // back to just the "~/.lldbinit" file. We also obey any requests to not
2274         // load the init files.
2275         const char *init_file_path = "~/.lldbinit";
2276 
2277         if (m_skip_app_init_files == false)
2278         {
2279             FileSpec program_file_spec (Host::GetProgramFileSpec());
2280             const char *program_name = program_file_spec.GetFilename().AsCString();
2281 
2282             if (program_name)
2283             {
2284                 char program_init_file_name[PATH_MAX];
2285                 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name);
2286                 init_file.SetFile (program_init_file_name, true);
2287                 if (!init_file.Exists())
2288                     init_file.Clear();
2289             }
2290         }
2291 
2292         if (!init_file && !m_skip_lldbinit_files)
2293 			init_file.SetFile (init_file_path, true);
2294     }
2295 
2296     // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
2297     // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
2298 
2299     if (init_file.Exists())
2300     {
2301         ExecutionContext *exe_ctx = NULL;  // We don't have any context yet.
2302         bool stop_on_continue = true;
2303         bool stop_on_error    = false;
2304         bool echo_commands    = false;
2305         bool print_results    = false;
2306 
2307         HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, eLazyBoolNo, result);
2308     }
2309     else
2310     {
2311         // nothing to be done if the file doesn't exist
2312         result.SetStatus(eReturnStatusSuccessFinishNoResult);
2313     }
2314 }
2315 
2316 PlatformSP
2317 CommandInterpreter::GetPlatform (bool prefer_target_platform)
2318 {
2319     PlatformSP platform_sp;
2320     if (prefer_target_platform)
2321     {
2322         ExecutionContext exe_ctx(GetExecutionContext());
2323         Target *target = exe_ctx.GetTargetPtr();
2324         if (target)
2325             platform_sp = target->GetPlatform();
2326     }
2327 
2328     if (!platform_sp)
2329         platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
2330     return platform_sp;
2331 }
2332 
2333 void
2334 CommandInterpreter::HandleCommands (const StringList &commands,
2335                                     ExecutionContext *override_context,
2336                                     bool stop_on_continue,
2337                                     bool stop_on_error,
2338                                     bool echo_commands,
2339                                     bool print_results,
2340                                     LazyBool add_to_history,
2341                                     CommandReturnObject &result)
2342 {
2343     size_t num_lines = commands.GetSize();
2344 
2345     // If we are going to continue past a "continue" then we need to run the commands synchronously.
2346     // Make sure you reset this value anywhere you return from the function.
2347 
2348     bool old_async_execution = m_debugger.GetAsyncExecution();
2349 
2350     // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
2351     // cause series of commands that change the context, then do an operation that relies on that context to fail.
2352 
2353     if (override_context != NULL)
2354         UpdateExecutionContext (override_context);
2355 
2356     if (!stop_on_continue)
2357     {
2358         m_debugger.SetAsyncExecution (false);
2359     }
2360 
2361     for (int idx = 0; idx < num_lines; idx++)
2362     {
2363         const char *cmd = commands.GetStringAtIndex(idx);
2364         if (cmd[0] == '\0')
2365             continue;
2366 
2367         if (echo_commands)
2368         {
2369             result.AppendMessageWithFormat ("%s %s\n",
2370                                              GetPrompt(),
2371                                              cmd);
2372         }
2373 
2374         CommandReturnObject tmp_result;
2375         // If override_context is not NULL, pass no_context_switching = true for
2376         // HandleCommand() since we updated our context already.
2377         bool success = HandleCommand(cmd, add_to_history, tmp_result,
2378                                      NULL, /* override_context */
2379                                      true, /* repeat_on_empty_command */
2380                                      override_context != NULL /* no_context_switching */);
2381 
2382         if (print_results)
2383         {
2384             if (tmp_result.Succeeded())
2385               result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
2386         }
2387 
2388         if (!success || !tmp_result.Succeeded())
2389         {
2390             const char *error_msg = tmp_result.GetErrorData();
2391             if (error_msg == NULL || error_msg[0] == '\0')
2392                 error_msg = "<unknown error>.\n";
2393             if (stop_on_error)
2394             {
2395                 result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' failed with %s",
2396                                          idx, cmd, error_msg);
2397                 result.SetStatus (eReturnStatusFailed);
2398                 m_debugger.SetAsyncExecution (old_async_execution);
2399                 return;
2400             }
2401             else if (print_results)
2402             {
2403                 result.AppendMessageWithFormat ("Command #%d '%s' failed with %s",
2404                                                 idx + 1,
2405                                                 cmd,
2406                                                 error_msg);
2407             }
2408         }
2409 
2410         if (result.GetImmediateOutputStream())
2411             result.GetImmediateOutputStream()->Flush();
2412 
2413         if (result.GetImmediateErrorStream())
2414             result.GetImmediateErrorStream()->Flush();
2415 
2416         // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
2417         // could be running (for instance in Breakpoint Commands.
2418         // So we check the return value to see if it is has running in it.
2419         if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
2420                 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
2421         {
2422             if (stop_on_continue)
2423             {
2424                 // If we caused the target to proceed, and we're going to stop in that case, set the
2425                 // status in our real result before returning.  This is an error if the continue was not the
2426                 // last command in the set of commands to be run.
2427                 if (idx != num_lines - 1)
2428                     result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' continued the target.\n",
2429                                                  idx + 1, cmd);
2430                 else
2431                     result.AppendMessageWithFormat ("Command #%d '%s' continued the target.\n", idx + 1, cmd);
2432 
2433                 result.SetStatus(tmp_result.GetStatus());
2434                 m_debugger.SetAsyncExecution (old_async_execution);
2435 
2436                 return;
2437             }
2438         }
2439 
2440     }
2441 
2442     result.SetStatus (eReturnStatusSuccessFinishResult);
2443     m_debugger.SetAsyncExecution (old_async_execution);
2444 
2445     return;
2446 }
2447 
2448 void
2449 CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
2450                                             ExecutionContext *context,
2451                                             bool stop_on_continue,
2452                                             bool stop_on_error,
2453                                             bool echo_command,
2454                                             bool print_result,
2455                                             LazyBool add_to_history,
2456                                             CommandReturnObject &result)
2457 {
2458     if (cmd_file.Exists())
2459     {
2460         bool success;
2461         StringList commands;
2462         success = commands.ReadFileLines(cmd_file);
2463         if (!success)
2464         {
2465             result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString());
2466             result.SetStatus (eReturnStatusFailed);
2467             return;
2468         }
2469         m_command_source_depth++;
2470         HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, add_to_history, result);
2471         m_command_source_depth--;
2472     }
2473     else
2474     {
2475         result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
2476                                       cmd_file.GetFilename().AsCString());
2477         result.SetStatus (eReturnStatusFailed);
2478         return;
2479     }
2480 }
2481 
2482 ScriptInterpreter *
2483 CommandInterpreter::GetScriptInterpreter ()
2484 {
2485     // <rdar://problem/11751427>
2486     // we need to protect the initialization of the script interpreter
2487     // otherwise we could end up with two threads both trying to create
2488     // their instance of it, and for some languages (e.g. Python)
2489     // this is a bulletproof recipe for disaster!
2490     // this needs to be a function-level static because multiple Debugger instances living in the same process
2491     // still need to be isolated and not try to initialize Python concurrently
2492     static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
2493     Mutex::Locker interpreter_lock(g_interpreter_mutex);
2494 
2495     if (m_script_interpreter_ap.get() != NULL)
2496         return m_script_interpreter_ap.get();
2497 
2498     lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
2499     switch (script_lang)
2500     {
2501         case eScriptLanguagePython:
2502 #ifndef LLDB_DISABLE_PYTHON
2503             m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
2504             break;
2505 #else
2506             // Fall through to the None case when python is disabled
2507 #endif
2508         case eScriptLanguageNone:
2509             m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
2510             break;
2511         default:
2512             break;
2513     };
2514 
2515     return m_script_interpreter_ap.get();
2516 }
2517 
2518 
2519 
2520 bool
2521 CommandInterpreter::GetSynchronous ()
2522 {
2523     return m_synchronous_execution;
2524 }
2525 
2526 void
2527 CommandInterpreter::SetSynchronous (bool value)
2528 {
2529     m_synchronous_execution  = value;
2530 }
2531 
2532 void
2533 CommandInterpreter::OutputFormattedHelpText (Stream &strm,
2534                                              const char *word_text,
2535                                              const char *separator,
2536                                              const char *help_text,
2537                                              uint32_t max_word_len)
2538 {
2539     const uint32_t max_columns = m_debugger.GetTerminalWidth();
2540 
2541     int indent_size = max_word_len + strlen (separator) + 2;
2542 
2543     strm.IndentMore (indent_size);
2544 
2545     StreamString text_strm;
2546     text_strm.Printf ("%-*s %s %s",  max_word_len, word_text, separator, help_text);
2547 
2548     size_t len = text_strm.GetSize();
2549     const char *text = text_strm.GetData();
2550     if (text[len - 1] == '\n')
2551     {
2552         text_strm.EOL();
2553         len = text_strm.GetSize();
2554     }
2555 
2556     if (len  < max_columns)
2557     {
2558         // Output it as a single line.
2559         strm.Printf ("%s", text);
2560     }
2561     else
2562     {
2563         // We need to break it up into multiple lines.
2564         bool first_line = true;
2565         int text_width;
2566         int start = 0;
2567         int end = start;
2568         int final_end = strlen (text);
2569         int sub_len;
2570 
2571         while (end < final_end)
2572         {
2573             if (first_line)
2574                 text_width = max_columns - 1;
2575             else
2576                 text_width = max_columns - indent_size - 1;
2577 
2578             // Don't start the 'text' on a space, since we're already outputting the indentation.
2579             if (!first_line)
2580             {
2581                 while ((start < final_end) && (text[start] == ' '))
2582                   start++;
2583             }
2584 
2585             end = start + text_width;
2586             if (end > final_end)
2587                 end = final_end;
2588             else
2589             {
2590                 // If we're not at the end of the text, make sure we break the line on white space.
2591                 while (end > start
2592                        && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
2593                     end--;
2594                 assert (end > 0);
2595             }
2596 
2597             sub_len = end - start;
2598             if (start != 0)
2599               strm.EOL();
2600             if (!first_line)
2601                 strm.Indent();
2602             else
2603                 first_line = false;
2604             assert (start <= final_end);
2605             assert (start + sub_len <= final_end);
2606             if (sub_len > 0)
2607                 strm.Write (text + start, sub_len);
2608             start = end + 1;
2609         }
2610     }
2611     strm.EOL();
2612     strm.IndentLess(indent_size);
2613 }
2614 
2615 void
2616 CommandInterpreter::OutputHelpText (Stream &strm,
2617                                     const char *word_text,
2618                                     const char *separator,
2619                                     const char *help_text,
2620                                     uint32_t max_word_len)
2621 {
2622     int indent_size = max_word_len + strlen (separator) + 2;
2623 
2624     strm.IndentMore (indent_size);
2625 
2626     StreamString text_strm;
2627     text_strm.Printf ("%-*s %s %s",  max_word_len, word_text, separator, help_text);
2628 
2629     const uint32_t max_columns = m_debugger.GetTerminalWidth();
2630 
2631     size_t len = text_strm.GetSize();
2632     const char *text = text_strm.GetData();
2633 
2634     uint32_t chars_left = max_columns;
2635 
2636     for (uint32_t i = 0; i < len; i++)
2637     {
2638         if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
2639         {
2640             chars_left = max_columns - indent_size;
2641             strm.EOL();
2642             strm.Indent();
2643         }
2644         else
2645         {
2646             strm.PutChar(text[i]);
2647             chars_left--;
2648         }
2649 
2650     }
2651 
2652     strm.EOL();
2653     strm.IndentLess(indent_size);
2654 }
2655 
2656 void
2657 CommandInterpreter::AproposAllSubCommands (CommandObject *cmd_obj, const char *prefix, const char *search_word,
2658                                            StringList &commands_found, StringList &commands_help)
2659 {
2660     CommandObject::CommandMap::const_iterator pos;
2661     CommandObject::CommandMap sub_cmd_dict = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict;
2662     CommandObject *sub_cmd_obj;
2663 
2664     for (pos = sub_cmd_dict.begin(); pos != sub_cmd_dict.end(); ++pos)
2665     {
2666           const char * command_name = pos->first.c_str();
2667           sub_cmd_obj = pos->second.get();
2668           StreamString complete_command_name;
2669 
2670           complete_command_name.Printf ("%s %s", prefix, command_name);
2671 
2672           if (sub_cmd_obj->HelpTextContainsWord (search_word))
2673           {
2674               commands_found.AppendString (complete_command_name.GetData());
2675               commands_help.AppendString (sub_cmd_obj->GetHelp());
2676           }
2677 
2678           if (sub_cmd_obj->IsMultiwordObject())
2679               AproposAllSubCommands (sub_cmd_obj, complete_command_name.GetData(), search_word, commands_found,
2680                                      commands_help);
2681     }
2682 
2683 }
2684 
2685 void
2686 CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
2687                                             StringList &commands_help)
2688 {
2689     CommandObject::CommandMap::const_iterator pos;
2690 
2691     for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
2692     {
2693         const char *command_name = pos->first.c_str();
2694         CommandObject *cmd_obj = pos->second.get();
2695 
2696         if (cmd_obj->HelpTextContainsWord (search_word))
2697         {
2698             commands_found.AppendString (command_name);
2699             commands_help.AppendString (cmd_obj->GetHelp());
2700         }
2701 
2702         if (cmd_obj->IsMultiwordObject())
2703           AproposAllSubCommands (cmd_obj, command_name, search_word, commands_found, commands_help);
2704 
2705     }
2706 }
2707 
2708 
2709 void
2710 CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
2711 {
2712     if (override_context != NULL)
2713     {
2714         m_exe_ctx_ref = *override_context;
2715     }
2716     else
2717     {
2718         const bool adopt_selected = true;
2719         m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
2720     }
2721 }
2722 
2723 void
2724 CommandInterpreter::DumpHistory (Stream &stream, uint32_t count) const
2725 {
2726     DumpHistory (stream, 0, count - 1);
2727 }
2728 
2729 void
2730 CommandInterpreter::DumpHistory (Stream &stream, uint32_t start, uint32_t end) const
2731 {
2732     const size_t last_idx = std::min<size_t>(m_command_history.size(), end + 1);
2733     for (size_t i = start; i < last_idx; i++)
2734     {
2735         if (!m_command_history[i].empty())
2736         {
2737             stream.Indent();
2738             stream.Printf ("%4zu: %s\n", i, m_command_history[i].c_str());
2739         }
2740     }
2741 }
2742 
2743 const char *
2744 CommandInterpreter::FindHistoryString (const char *input_str) const
2745 {
2746     if (input_str[0] != m_repeat_char)
2747         return NULL;
2748     if (input_str[1] == '-')
2749     {
2750         bool success;
2751         uint32_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success);
2752         if (!success)
2753             return NULL;
2754         if (idx > m_command_history.size())
2755             return NULL;
2756         idx = m_command_history.size() - idx;
2757         return m_command_history[idx].c_str();
2758 
2759     }
2760     else if (input_str[1] == m_repeat_char)
2761     {
2762         if (m_command_history.empty())
2763             return NULL;
2764         else
2765             return m_command_history.back().c_str();
2766     }
2767     else
2768     {
2769         bool success;
2770         uint32_t idx = Args::StringToUInt32 (input_str+1, 0, 0, &success);
2771         if (!success)
2772             return NULL;
2773         if (idx >= m_command_history.size())
2774             return NULL;
2775         return m_command_history[idx].c_str();
2776     }
2777 }
2778