blob: 2b4155d49237ba43c8e6f039298439d9b84fcc4a [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
12#include <getopt.h>
13#include <stdlib.h>
14
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000015#include "../Commands/CommandObjectAppend.h"
16#include "../Commands/CommandObjectApropos.h"
17#include "../Commands/CommandObjectArgs.h"
18#include "../Commands/CommandObjectBreakpoint.h"
Sean Callanan65dafa82010-08-27 01:01:44 +000019//#include "../Commands/CommandObjectCall.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000020#include "../Commands/CommandObjectDisassemble.h"
21#include "../Commands/CommandObjectExpression.h"
22#include "../Commands/CommandObjectFile.h"
23#include "../Commands/CommandObjectFrame.h"
24#include "../Commands/CommandObjectHelp.h"
25#include "../Commands/CommandObjectImage.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000026#include "../Commands/CommandObjectLog.h"
27#include "../Commands/CommandObjectMemory.h"
28#include "../Commands/CommandObjectProcess.h"
29#include "../Commands/CommandObjectQuit.h"
Eli Friedmanb34d2a22010-06-09 22:08:29 +000030#include "lldb/Interpreter/CommandObjectRegexCommand.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000031#include "../Commands/CommandObjectRegister.h"
Chris Lattner24943d22010-06-08 16:52:24 +000032#include "CommandObjectScript.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000033#include "../Commands/CommandObjectSet.h"
34#include "../Commands/CommandObjectSettings.h"
35#include "../Commands/CommandObjectShow.h"
36#include "../Commands/CommandObjectSource.h"
Jim Ingham767af882010-07-07 03:36:20 +000037#include "../Commands/CommandObjectCommands.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000038#include "../Commands/CommandObjectSyntax.h"
39#include "../Commands/CommandObjectTarget.h"
40#include "../Commands/CommandObjectThread.h"
Chris Lattner24943d22010-06-08 16:52:24 +000041
Jim Ingham84cdc152010-06-15 19:49:27 +000042#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000043#include "lldb/Core/Debugger.h"
44#include "lldb/Core/Stream.h"
45#include "lldb/Core/Timer.h"
46#include "lldb/Target/Process.h"
47#include "lldb/Target/Thread.h"
48#include "lldb/Target/TargetList.h"
49
50#include "lldb/Interpreter/CommandReturnObject.h"
51#include "lldb/Interpreter/CommandInterpreter.h"
52
53using namespace lldb;
54using namespace lldb_private;
55
56CommandInterpreter::CommandInterpreter
57(
Greg Clayton63094e02010-06-23 01:19:29 +000058 Debugger &debugger,
Chris Lattner24943d22010-06-08 16:52:24 +000059 ScriptLanguage script_language,
Greg Clayton63094e02010-06-23 01:19:29 +000060 bool synchronous_execution
Chris Lattner24943d22010-06-08 16:52:24 +000061) :
62 Broadcaster ("CommandInterpreter"),
Greg Clayton63094e02010-06-23 01:19:29 +000063 m_debugger (debugger),
Chris Lattner24943d22010-06-08 16:52:24 +000064 m_script_language (script_language),
Greg Clayton63094e02010-06-23 01:19:29 +000065 m_synchronous_execution (synchronous_execution)
Chris Lattner24943d22010-06-08 16:52:24 +000066{
67}
68
69void
70CommandInterpreter::Initialize ()
71{
72 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
73
74 CommandReturnObject result;
75
76 LoadCommandDictionary ();
77
78 InitializeVariables ();
79
80 // Set up some initial aliases.
Jim Ingham767af882010-07-07 03:36:20 +000081 result.Clear(); HandleCommand ("command alias q quit", false, result);
82 result.Clear(); HandleCommand ("command alias run process launch", false, result);
83 result.Clear(); HandleCommand ("command alias r process launch", false, result);
84 result.Clear(); HandleCommand ("command alias c process continue", false, result);
85 result.Clear(); HandleCommand ("command alias continue process continue", false, result);
86 result.Clear(); HandleCommand ("command alias expr expression", false, result);
87 result.Clear(); HandleCommand ("command alias exit quit", false, result);
88 result.Clear(); HandleCommand ("command alias b breakpoint", false, result);
89 result.Clear(); HandleCommand ("command alias bt thread backtrace", false, result);
90 result.Clear(); HandleCommand ("command alias si thread step-inst", false, result);
91 result.Clear(); HandleCommand ("command alias step thread step-in", false, result);
92 result.Clear(); HandleCommand ("command alias s thread step-in", false, result);
93 result.Clear(); HandleCommand ("command alias next thread step-over", false, result);
94 result.Clear(); HandleCommand ("command alias n thread step-over", false, result);
95 result.Clear(); HandleCommand ("command alias finish thread step-out", false, result);
96 result.Clear(); HandleCommand ("command alias x memory read", false, result);
97 result.Clear(); HandleCommand ("command alias l source list", false, result);
98 result.Clear(); HandleCommand ("command alias list source list", false, result);
Chris Lattner24943d22010-06-08 16:52:24 +000099}
100
101void
102CommandInterpreter::InitializeVariables ()
103{
104 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
105
106 m_variables["prompt"] =
107 StateVariableSP (new StateVariable ("prompt",
108 "(lldb) ",
109 false,
110 "The debugger prompt displayed for the user.",
111 StateVariable::BroadcastPromptChange));
112
113 m_variables["run-args"] =
114 StateVariableSP (new StateVariable ("run-args",
115 (Args*)NULL,
116 "An argument list containing the arguments to be passed to the executable when it is launched."));
117
118
119 m_variables["env-vars"] =
120 StateVariableSP (new StateVariable ("env-vars",
121 (Args*)NULL,
122 "A list of strings containing the environment variables to be passed to the executable's environment."));
123
124 m_variables["input-path"] =
125 StateVariableSP (new StateVariable ("input-path",
126 "/dev/stdin",
127 false,
128 "The file/path to be used by the executable program for reading its input."));
129
130 m_variables["output-path"] =
131 StateVariableSP (new StateVariable ( "output-path",
132 "/dev/stdout",
133 false,
134 "The file/path to be used by the executable program for writing its output."));
135
136 m_variables["error-path"] =
137 StateVariableSP (new StateVariable ("error-path",
138 "/dev/stderr",
139 false,
140 "The file/path to be used by the executable program for writing its error messages."));
141
142 m_variables["arch"] =
143 StateVariableSP (new StateVariable ("arch",
144 "",
145 false,
146 "The architecture to be used for running the executable (e.g. i386, x86_64, etc)."));
147
148 m_variables["script-lang"] =
149 StateVariableSP (new StateVariable ("script-lang",
150 "Python",
151 false,
152 "The script language to be used for evaluating user-written scripts.",
153 StateVariable::VerifyScriptLanguage));
154
155 m_variables["term-width"] =
156 StateVariableSP (new StateVariable ("term-width",
157 80,
158 "The maximum number of columns to use for displaying text."));
159
Greg Clayton452bf612010-08-31 18:35:14 +0000160 m_variables["disable-aslr"] =
161 StateVariableSP (new StateVariable ("disable-aslr",
162 1,
163 "Disable Address Space Layout Randomization (ASLR)."));
164
Chris Lattner24943d22010-06-08 16:52:24 +0000165}
166
167const char *
168CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
169{
170 // This function has not yet been implemented.
171
172 // Look for any embedded script command
173 // If found,
174 // get interpreter object from the command dictionary,
175 // call execute_one_command on it,
176 // get the results as a string,
177 // substitute that string for current stuff.
178
179 return arg;
180}
181
182
183void
184CommandInterpreter::LoadCommandDictionary ()
185{
186 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
187
188 // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
189 //
190 // Command objects that are used as cross reference objects (i.e. they inherit from CommandObjectCrossref)
191 // *MUST* be created and put into the command dictionary *BEFORE* any multi-word commands (which may use
192 // the cross-referencing stuff) are created!!!
193 //
194 // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
195
196
197 // Command objects that inherit from CommandObjectCrossref must be created before other command objects
198 // are created. This is so that when another command is created that needs to go into a crossref object,
199 // the crossref object exists and is ready to take the cross reference. Put the cross referencing command
200 // objects into the CommandDictionary now, so they are ready for use when the other commands get created.
201
Chris Lattner24943d22010-06-08 16:52:24 +0000202 // Non-CommandObjectCrossref commands can now be created.
203
Chris Lattner24943d22010-06-08 16:52:24 +0000204 m_command_dict["append"] = CommandObjectSP (new CommandObjectAppend ());
205 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos ());
Greg Clayton63094e02010-06-23 01:19:29 +0000206 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
Sean Callanan65dafa82010-08-27 01:01:44 +0000207 //m_command_dict["call"] = CommandObjectSP (new CommandObjectCall ());
Jim Ingham767af882010-07-07 03:36:20 +0000208 m_command_dict["commands"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
Chris Lattner24943d22010-06-08 16:52:24 +0000209 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble ());
210 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression ());
211 m_command_dict["file"] = CommandObjectSP (new CommandObjectFile ());
Greg Clayton63094e02010-06-23 01:19:29 +0000212 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
Chris Lattner24943d22010-06-08 16:52:24 +0000213 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp ());
Greg Clayton63094e02010-06-23 01:19:29 +0000214 m_command_dict["image"] = CommandObjectSP (new CommandObjectImage (*this));
215 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this));
216 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this));
217 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
Chris Lattner24943d22010-06-08 16:52:24 +0000218 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit ());
Greg Clayton63094e02010-06-23 01:19:29 +0000219 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this));
Chris Lattner24943d22010-06-08 16:52:24 +0000220 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (m_script_language));
221 m_command_dict["set"] = CommandObjectSP (new CommandObjectSet ());
222 m_command_dict["settings"] = CommandObjectSP (new CommandObjectSettings ());
223 m_command_dict["show"] = CommandObjectSP (new CommandObjectShow ());
Jim Ingham767af882010-07-07 03:36:20 +0000224 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000225 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
226 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this));
Chris Lattner24943d22010-06-08 16:52:24 +0000227
228 std::auto_ptr<CommandObjectRegexCommand>
229 break_regex_cmd_ap(new CommandObjectRegexCommand ("regexp-break",
230 "Smart breakpoint command (using regular expressions).",
231 "regexp-break [<file>:<line>]\nregexp-break [<address>]\nregexp-break <...>", 2));
232 if (break_regex_cmd_ap.get())
233 {
234 if (break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2") &&
235 break_regex_cmd_ap->AddRegexCommand("^(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1") &&
236 break_regex_cmd_ap->AddRegexCommand("^[\"']?([-+]\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'") &&
237 break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list") &&
238 break_regex_cmd_ap->AddRegexCommand("^(-.*)$", "breakpoint set %1") &&
239 break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"))
240 {
241 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
242 m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
243 }
244 }
245}
246
247int
248CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
249 StringList &matches)
250{
251 CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
252
253 if (include_aliases)
254 {
255 CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
256 }
257
258 return matches.GetSize();
259}
260
261CommandObjectSP
262CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
263{
264 CommandObject::CommandMap::iterator pos;
265 CommandObjectSP ret_val;
266
267 std::string cmd(cmd_cstr);
268
269 if (HasCommands())
270 {
271 pos = m_command_dict.find(cmd);
272 if (pos != m_command_dict.end())
273 ret_val = pos->second;
274 }
275
276 if (include_aliases && HasAliases())
277 {
278 pos = m_alias_dict.find(cmd);
279 if (pos != m_alias_dict.end())
280 ret_val = pos->second;
281 }
282
283 if (HasUserCommands())
284 {
285 pos = m_user_dict.find(cmd);
286 if (pos != m_user_dict.end())
287 ret_val = pos->second;
288 }
289
290 if (!exact && ret_val == NULL)
291 {
Jim Inghamd40f8a62010-07-06 22:46:59 +0000292 // We will only get into here if we didn't find any exact matches.
293
294 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
295
Chris Lattner24943d22010-06-08 16:52:24 +0000296 StringList local_matches;
297 if (matches == NULL)
298 matches = &local_matches;
299
Jim Inghamd40f8a62010-07-06 22:46:59 +0000300 unsigned int num_cmd_matches = 0;
301 unsigned int num_alias_matches = 0;
302 unsigned int num_user_matches = 0;
303
304 // Look through the command dictionaries one by one, and if we get only one match from any of
305 // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
306
Chris Lattner24943d22010-06-08 16:52:24 +0000307 if (HasCommands())
308 {
309 num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
310 }
311
312 if (num_cmd_matches == 1)
313 {
314 cmd.assign(matches->GetStringAtIndex(0));
315 pos = m_command_dict.find(cmd);
316 if (pos != m_command_dict.end())
Jim Inghamd40f8a62010-07-06 22:46:59 +0000317 real_match_sp = pos->second;
Chris Lattner24943d22010-06-08 16:52:24 +0000318 }
319
Jim Ingham9a574172010-06-24 20:28:42 +0000320 if (include_aliases && HasAliases())
Chris Lattner24943d22010-06-08 16:52:24 +0000321 {
322 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
323
324 }
325
Jim Inghamd40f8a62010-07-06 22:46:59 +0000326 if (num_alias_matches == 1)
Chris Lattner24943d22010-06-08 16:52:24 +0000327 {
328 cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
329 pos = m_alias_dict.find(cmd);
330 if (pos != m_alias_dict.end())
Jim Inghamd40f8a62010-07-06 22:46:59 +0000331 alias_match_sp = pos->second;
Chris Lattner24943d22010-06-08 16:52:24 +0000332 }
333
Jim Ingham9a574172010-06-24 20:28:42 +0000334 if (HasUserCommands())
Chris Lattner24943d22010-06-08 16:52:24 +0000335 {
336 num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
337 }
338
Jim Inghamd40f8a62010-07-06 22:46:59 +0000339 if (num_user_matches == 1)
Chris Lattner24943d22010-06-08 16:52:24 +0000340 {
341 cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
342
343 pos = m_user_dict.find (cmd);
344 if (pos != m_user_dict.end())
Jim Inghamd40f8a62010-07-06 22:46:59 +0000345 user_match_sp = pos->second;
346 }
347
348 // If we got exactly one match, return that, otherwise return the match list.
349
350 if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
351 {
352 if (num_cmd_matches)
353 return real_match_sp;
354 else if (num_alias_matches)
355 return alias_match_sp;
356 else
357 return user_match_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000358 }
359 }
Jim Inghamd40f8a62010-07-06 22:46:59 +0000360 else if (matches && ret_val != NULL)
361 {
362 matches->AppendString (cmd_cstr);
Chris Lattner24943d22010-06-08 16:52:24 +0000363 }
364
365
366 return ret_val;
367}
368
Jim Inghamd40f8a62010-07-06 22:46:59 +0000369CommandObjectSP
370CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
Chris Lattner24943d22010-06-08 16:52:24 +0000371{
Jim Inghamd40f8a62010-07-06 22:46:59 +0000372 return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
373}
374
375CommandObject *
376CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
377{
378 return GetCommandSPExact (cmd_cstr, include_aliases).get();
379}
380
381CommandObject *
382CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
383{
384 CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
385
386 // If we didn't find an exact match to the command string in the commands, look in
387 // the aliases.
388
389 if (command_obj == NULL)
390 {
391 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
392 }
393
394 // Finally, if there wasn't an exact match among the aliases, look for an inexact match
395 // in both the commands and the aliases.
396
397 if (command_obj == NULL)
398 command_obj = GetCommandSP(cmd_cstr, true, false, matches).get();
399
400 return command_obj;
Chris Lattner24943d22010-06-08 16:52:24 +0000401}
402
403bool
404CommandInterpreter::CommandExists (const char *cmd)
405{
406 return m_command_dict.find(cmd) != m_command_dict.end();
407}
408
409bool
410CommandInterpreter::AliasExists (const char *cmd)
411{
412 return m_alias_dict.find(cmd) != m_alias_dict.end();
413}
414
415bool
416CommandInterpreter::UserCommandExists (const char *cmd)
417{
418 return m_user_dict.find(cmd) != m_user_dict.end();
419}
420
421void
422CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
423{
Jim Inghamd40f8a62010-07-06 22:46:59 +0000424 command_obj_sp->SetIsAlias (true);
Chris Lattner24943d22010-06-08 16:52:24 +0000425 m_alias_dict[alias_name] = command_obj_sp;
426}
427
428bool
429CommandInterpreter::RemoveAlias (const char *alias_name)
430{
431 CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
432 if (pos != m_alias_dict.end())
433 {
434 m_alias_dict.erase(pos);
435 return true;
436 }
437 return false;
438}
439bool
440CommandInterpreter::RemoveUser (const char *alias_name)
441{
442 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
443 if (pos != m_user_dict.end())
444 {
445 m_user_dict.erase(pos);
446 return true;
447 }
448 return false;
449}
450
451StateVariable *
452CommandInterpreter::GetStateVariable(const char *name)
453{
454 VariableMap::const_iterator pos = m_variables.find(name);
455 if (pos != m_variables.end())
456 return pos->second.get();
457 return NULL;
458}
459
460void
461CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
462{
463 help_string.Printf ("'%s", command_name);
464 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
465
466 if (option_arg_vector_sp != NULL)
467 {
468 OptionArgVector *options = option_arg_vector_sp.get();
469 for (int i = 0; i < options->size(); ++i)
470 {
471 OptionArgPair cur_option = (*options)[i];
472 std::string opt = cur_option.first;
473 std::string value = cur_option.second;
474 if (opt.compare("<argument>") == 0)
475 {
476 help_string.Printf (" %s", value.c_str());
477 }
478 else
479 {
480 help_string.Printf (" %s", opt.c_str());
481 if ((value.compare ("<no-argument>") != 0)
482 && (value.compare ("<need-argument") != 0))
483 {
484 help_string.Printf (" %s", value.c_str());
485 }
486 }
487 }
488 }
489
490 help_string.Printf ("'");
491}
492
Greg Clayton65124ea2010-08-26 22:05:43 +0000493size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000494CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
495{
496 CommandObject::CommandMap::const_iterator pos;
Greg Clayton65124ea2010-08-26 22:05:43 +0000497 CommandObject::CommandMap::const_iterator end = dict.end();
498 size_t max_len = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000499
Greg Clayton65124ea2010-08-26 22:05:43 +0000500 for (pos = dict.begin(); pos != end; ++pos)
501 {
502 size_t len = pos->first.size();
503 if (max_len < len)
504 max_len = len;
Chris Lattner24943d22010-06-08 16:52:24 +0000505 }
Greg Clayton65124ea2010-08-26 22:05:43 +0000506 return max_len;
Chris Lattner24943d22010-06-08 16:52:24 +0000507}
508
509void
510CommandInterpreter::GetHelp (CommandReturnObject &result)
511{
512 CommandObject::CommandMap::const_iterator pos;
513 result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
514 result.AppendMessage("");
Greg Clayton65124ea2010-08-26 22:05:43 +0000515 uint32_t max_len = FindLongestCommandWord (m_command_dict);
Chris Lattner24943d22010-06-08 16:52:24 +0000516
517 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
518 {
519 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
520 max_len);
521 }
522 result.AppendMessage("");
523
524 if (m_alias_dict.size() > 0)
525 {
Sean Callanana3aff732010-08-09 18:50:15 +0000526 result.AppendMessage("The following is a list of your current command abbreviations (see 'commands alias' for more info):");
Chris Lattner24943d22010-06-08 16:52:24 +0000527 result.AppendMessage("");
Greg Clayton65124ea2010-08-26 22:05:43 +0000528 max_len = FindLongestCommandWord (m_alias_dict);
529
Chris Lattner24943d22010-06-08 16:52:24 +0000530 for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
531 {
532 StreamString sstr;
533 StreamString translation_and_help;
534 std::string entry_name = pos->first;
535 std::string second_entry = pos->second.get()->GetCommandName();
536 GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
537
538 translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp());
539 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
540 translation_and_help.GetData(), max_len);
541 }
542 result.AppendMessage("");
543 }
544
545 if (m_user_dict.size() > 0)
546 {
547 result.AppendMessage ("The following is a list of your current user-defined commands:");
548 result.AppendMessage("");
549 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
550 {
551 result.AppendMessageWithFormat ("%s -- %s\n", pos->first.c_str(), pos->second->GetHelp());
552 }
553 result.AppendMessage("");
554 }
555
556 result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
557}
558
559void
560CommandInterpreter::ShowVariableValues (CommandReturnObject &result)
561{
562 result.AppendMessage ("Below is a list of all the debugger setting variables and their values:");
563
564 for (VariableMap::const_iterator pos = m_variables.begin(); pos != m_variables.end(); ++pos)
565 {
566 StateVariable *var = pos->second.get();
567 var->AppendVariableInformation (result);
568 }
569}
570
571void
572CommandInterpreter::ShowVariableHelp (CommandReturnObject &result)
573{
574 result.AppendMessage ("Below is a list of all the internal debugger variables that are settable:");
575 for (VariableMap::const_iterator pos = m_variables.begin(); pos != m_variables.end(); ++pos)
576 {
577 StateVariable *var = pos->second.get();
578 result.AppendMessageWithFormat (" %s -- %s \n", var->GetName(), var->GetHelp());
579 }
580}
581
582// Main entry point into the command_interpreter; this function takes a text
583// line containing a debugger command, with all its flags, options, etc,
584// parses the line and takes the appropriate actions.
585
586bool
Greg Clayton63094e02010-06-23 01:19:29 +0000587CommandInterpreter::HandleCommand
588(
589 const char *command_line,
590 bool add_to_history,
591 CommandReturnObject &result,
592 ExecutionContext *override_context
593)
Chris Lattner24943d22010-06-08 16:52:24 +0000594{
595 // FIXME: there should probably be a mutex to make sure only one thread can
596 // run the interpreter at a time.
597
598 // TODO: this should be a logging channel in lldb.
599// if (DebugSelf())
600// {
601// result.AppendMessageWithFormat ("Processing command: %s\n", command_line);
602// }
603
Greg Clayton63094e02010-06-23 01:19:29 +0000604 m_debugger.UpdateExecutionContext (override_context);
Chris Lattner24943d22010-06-08 16:52:24 +0000605
606 if (command_line == NULL || command_line[0] == '\0')
607 {
608 if (m_command_history.empty())
609 {
610 result.AppendError ("empty command");
611 result.SetStatus(eReturnStatusFailed);
612 return false;
613 }
614 else
615 {
Jim Ingham5d9cbd42010-07-06 23:48:33 +0000616 command_line = m_repeat_command.c_str();
617 if (m_repeat_command.empty())
618 {
Jim Ingham767af882010-07-07 03:36:20 +0000619 result.AppendErrorWithFormat("No auto repeat.\n");
Jim Ingham5d9cbd42010-07-06 23:48:33 +0000620 result.SetStatus (eReturnStatusFailed);
621 return false;
622 }
Chris Lattner24943d22010-06-08 16:52:24 +0000623 }
624 add_to_history = false;
625 }
626
627 Args command_args(command_line);
628
629 if (command_args.GetArgumentCount() > 0)
630 {
631 const char *command_cstr = command_args.GetArgumentAtIndex(0);
632 if (command_cstr)
633 {
634
635 // We're looking up the command object here. So first find an exact match to the
636 // command in the commands.
Jim Inghamd40f8a62010-07-06 22:46:59 +0000637 CommandObject *command_obj = GetCommandObject(command_cstr);
638
639 if (command_obj != NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000640 {
Jim Inghamd40f8a62010-07-06 22:46:59 +0000641 if (command_obj->IsAlias())
Chris Lattner24943d22010-06-08 16:52:24 +0000642 {
643 BuildAliasCommandArgs (command_obj, command_cstr, command_args, result);
644 if (!result.Succeeded())
645 return false;
646 }
Chris Lattner24943d22010-06-08 16:52:24 +0000647
Jim Ingham5d9cbd42010-07-06 23:48:33 +0000648 if (add_to_history)
649 {
Jim Ingham767af882010-07-07 03:36:20 +0000650 const char *repeat_command = command_obj->GetRepeatCommand(command_args, 0);
651 if (repeat_command != NULL)
Jim Ingham5d9cbd42010-07-06 23:48:33 +0000652 m_repeat_command.assign(repeat_command);
653 else
Jim Ingham767af882010-07-07 03:36:20 +0000654 m_repeat_command.assign(command_line);
Jim Ingham5d9cbd42010-07-06 23:48:33 +0000655
656 m_command_history.push_back (command_line);
657 }
658
659
Chris Lattner24943d22010-06-08 16:52:24 +0000660 if (command_obj->WantsRawCommandString())
661 {
662 const char *stripped_command = ::strstr (command_line, command_cstr);
663 if (stripped_command)
664 {
665 stripped_command += strlen(command_cstr);
666 while (isspace(*stripped_command))
667 ++stripped_command;
Greg Clayton63094e02010-06-23 01:19:29 +0000668 command_obj->ExecuteRawCommandString (*this, stripped_command, result);
Chris Lattner24943d22010-06-08 16:52:24 +0000669 }
670 }
671 else
672 {
Chris Lattner24943d22010-06-08 16:52:24 +0000673 // Remove the command from the args.
674 command_args.Shift();
Greg Clayton63094e02010-06-23 01:19:29 +0000675 command_obj->ExecuteWithOptions (*this, command_args, result);
Chris Lattner24943d22010-06-08 16:52:24 +0000676 }
677 }
678 else
679 {
Jim Inghamd40f8a62010-07-06 22:46:59 +0000680 // We didn't find the first command object, so complete the first argument.
Chris Lattner24943d22010-06-08 16:52:24 +0000681 StringList matches;
682 int num_matches;
Jim Inghamd40f8a62010-07-06 22:46:59 +0000683 int cursor_index = 0;
684 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
Jim Ingham802f8b02010-06-30 05:02:46 +0000685 bool word_complete;
Greg Clayton63094e02010-06-23 01:19:29 +0000686 num_matches = HandleCompletionMatches (command_args,
687 cursor_index,
688 cursor_char_position,
689 0,
690 -1,
Jim Ingham802f8b02010-06-30 05:02:46 +0000691 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000692 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000693
694 if (num_matches > 0)
695 {
696 std::string error_msg;
697 error_msg.assign ("ambiguous command '");
698 error_msg.append(command_cstr);
699 error_msg.append ("'.");
700
701 error_msg.append (" Possible completions:");
702 for (int i = 0; i < num_matches; i++)
703 {
704 error_msg.append ("\n\t");
705 error_msg.append (matches.GetStringAtIndex (i));
706 }
707 error_msg.append ("\n");
708 result.AppendRawError (error_msg.c_str(), error_msg.size());
709 }
710 else
711 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_cstr);
712
713 result.SetStatus (eReturnStatusFailed);
714 }
715 }
716 }
717 return result.Succeeded();
718}
719
720int
721CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
722 int &cursor_index,
723 int &cursor_char_position,
724 int match_start_point,
725 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000726 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000727 StringList &matches)
728{
729 int num_command_matches = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000730 bool look_for_subcommand = false;
Jim Ingham802f8b02010-06-30 05:02:46 +0000731
732 // For any of the command completions a unique match will be a complete word.
733 word_complete = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000734
735 if (cursor_index == -1)
736 {
737 // We got nothing on the command line, so return the list of commands
Jim Inghamd40f8a62010-07-06 22:46:59 +0000738 bool include_aliases = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000739 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
740 }
741 else if (cursor_index == 0)
742 {
743 // The cursor is in the first argument, so just do a lookup in the dictionary.
Jim Inghamd40f8a62010-07-06 22:46:59 +0000744 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000745 num_command_matches = matches.GetSize();
746
747 if (num_command_matches == 1
748 && cmd_obj && cmd_obj->IsMultiwordObject()
749 && matches.GetStringAtIndex(0) != NULL
750 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
751 {
752 look_for_subcommand = true;
753 num_command_matches = 0;
754 matches.DeleteStringAtIndex(0);
755 parsed_line.AppendArgument ("");
756 cursor_index++;
757 cursor_char_position = 0;
758 }
759 }
760
761 if (cursor_index > 0 || look_for_subcommand)
762 {
763 // We are completing further on into a commands arguments, so find the command and tell it
764 // to complete the command.
765 // First see if there is a matching initial command:
Jim Inghamd40f8a62010-07-06 22:46:59 +0000766 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
Chris Lattner24943d22010-06-08 16:52:24 +0000767 if (command_object == NULL)
768 {
769 return 0;
770 }
771 else
772 {
773 parsed_line.Shift();
774 cursor_index--;
Greg Clayton63094e02010-06-23 01:19:29 +0000775 num_command_matches = command_object->HandleCompletion (*this,
776 parsed_line,
777 cursor_index,
778 cursor_char_position,
779 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000780 max_return_elements,
781 word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000782 matches);
783 }
784 }
785
786 return num_command_matches;
787
788}
789
790int
791CommandInterpreter::HandleCompletion (const char *current_line,
792 const char *cursor,
793 const char *last_char,
794 int match_start_point,
795 int max_return_elements,
796 StringList &matches)
797{
798 // We parse the argument up to the cursor, so the last argument in parsed_line is
799 // the one containing the cursor, and the cursor is after the last character.
800
801 Args parsed_line(current_line, last_char - current_line);
802 Args partial_parsed_line(current_line, cursor - current_line);
803
804 int num_args = partial_parsed_line.GetArgumentCount();
805 int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
806 int cursor_char_position;
807
808 if (cursor_index == -1)
809 cursor_char_position = 0;
810 else
811 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
812
813 int num_command_matches;
814
815 matches.Clear();
816
817 // Only max_return_elements == -1 is supported at present:
818 assert (max_return_elements == -1);
Jim Ingham802f8b02010-06-30 05:02:46 +0000819 bool word_complete;
Greg Clayton63094e02010-06-23 01:19:29 +0000820 num_command_matches = HandleCompletionMatches (parsed_line,
821 cursor_index,
822 cursor_char_position,
823 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000824 max_return_elements,
825 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000826 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000827
828 if (num_command_matches <= 0)
829 return num_command_matches;
830
831 if (num_args == 0)
832 {
833 // If we got an empty string, insert nothing.
834 matches.InsertStringAtIndex(0, "");
835 }
836 else
837 {
838 // Now figure out if there is a common substring, and if so put that in element 0, otherwise
839 // put an empty string in element 0.
840 std::string command_partial_str;
841 if (cursor_index >= 0)
842 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
843
844 std::string common_prefix;
845 matches.LongestCommonPrefix (common_prefix);
846 int partial_name_len = command_partial_str.size();
847
848 // If we matched a unique single command, add a space...
Jim Ingham802f8b02010-06-30 05:02:46 +0000849 // Only do this if the completer told us this was a complete word, however...
850 if (num_command_matches == 1 && word_complete)
Chris Lattner24943d22010-06-08 16:52:24 +0000851 {
852 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
853 if (quote_char != '\0')
854 common_prefix.push_back(quote_char);
855
856 common_prefix.push_back(' ');
857 }
858 common_prefix.erase (0, partial_name_len);
859 matches.InsertStringAtIndex(0, common_prefix.c_str());
860 }
861 return num_command_matches;
862}
863
Chris Lattner24943d22010-06-08 16:52:24 +0000864const Args *
865CommandInterpreter::GetProgramArguments ()
866{
867 if (! HasInterpreterVariables())
868 return NULL;
869
870 VariableMap::const_iterator pos = m_variables.find("run-args");
871 if (pos == m_variables.end())
872 return NULL;
873
874 StateVariable *var = pos->second.get();
875
876 if (var)
877 return &var->GetArgs();
878 return NULL;
879}
880
881const Args *
882CommandInterpreter::GetEnvironmentVariables ()
883{
884 if (! HasInterpreterVariables())
885 return NULL;
886
887 VariableMap::const_iterator pos = m_variables.find("env-vars");
888 if (pos == m_variables.end())
889 return NULL;
890
891 StateVariable *var = pos->second.get();
892 if (var)
893 return &var->GetArgs();
894 return NULL;
895}
896
Greg Clayton452bf612010-08-31 18:35:14 +0000897int
898CommandInterpreter::GetDisableASLR ()
899{
900 StateVariable *var = GetStateVariable ("disable-aslr");
901 int disable_aslr = var->GetIntValue();
902
903 return disable_aslr;
904}
Chris Lattner24943d22010-06-08 16:52:24 +0000905
906CommandInterpreter::~CommandInterpreter ()
907{
908}
909
910const char *
911CommandInterpreter::GetPrompt ()
912{
913 VariableMap::iterator pos;
914
915 if (! HasInterpreterVariables())
916 return NULL;
917
918 pos = m_variables.find("prompt");
919 if (pos == m_variables.end())
920 return NULL;
921
922 StateVariable *var = pos->second.get();
923
924 return ((char *) var->GetStringValue());
925}
926
927void
928CommandInterpreter::SetPrompt (const char *new_prompt)
929{
930 VariableMap::iterator pos;
931 CommandReturnObject result;
932
933 if (! HasInterpreterVariables())
934 return;
935
936 pos = m_variables.find ("prompt");
937 if (pos == m_variables.end())
938 return;
939
940 StateVariable *var = pos->second.get();
941
942 if (var->VerifyValue (this, (void *) new_prompt, result))
943 var->SetStringValue (new_prompt);
944}
945
946void
947CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
948{
Jim Inghamd40f8a62010-07-06 22:46:59 +0000949 CommandObjectSP cmd_obj_sp = GetCommandSPExact (dest_cmd, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000950
951 if (cmd_obj_sp != NULL)
952 {
953 CommandObject *cmd_obj = cmd_obj_sp.get();
954 if (cmd_obj->IsCrossRefObject ())
955 cmd_obj->AddObject (object_type);
956 }
957}
958
959void
960CommandInterpreter::SetScriptLanguage (ScriptLanguage lang)
961{
962 m_script_language = lang;
963}
964
Chris Lattner24943d22010-06-08 16:52:24 +0000965OptionArgVectorSP
966CommandInterpreter::GetAliasOptions (const char *alias_name)
967{
968 OptionArgMap::iterator pos;
969 OptionArgVectorSP ret_val;
970
971 std::string alias (alias_name);
972
973 if (HasAliasOptions())
974 {
975 pos = m_alias_options.find (alias);
976 if (pos != m_alias_options.end())
977 ret_val = pos->second;
978 }
979
980 return ret_val;
981}
982
983void
984CommandInterpreter::RemoveAliasOptions (const char *alias_name)
985{
986 OptionArgMap::iterator pos = m_alias_options.find(alias_name);
987 if (pos != m_alias_options.end())
988 {
989 m_alias_options.erase (pos);
990 }
991}
992
993void
994CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
995{
996 m_alias_options[alias_name] = option_arg_vector_sp;
997}
998
999bool
1000CommandInterpreter::HasCommands ()
1001{
1002 return (!m_command_dict.empty());
1003}
1004
1005bool
1006CommandInterpreter::HasAliases ()
1007{
1008 return (!m_alias_dict.empty());
1009}
1010
1011bool
1012CommandInterpreter::HasUserCommands ()
1013{
1014 return (!m_user_dict.empty());
1015}
1016
1017bool
1018CommandInterpreter::HasAliasOptions ()
1019{
1020 return (!m_alias_options.empty());
1021}
1022
1023bool
1024CommandInterpreter::HasInterpreterVariables ()
1025{
1026 return (!m_variables.empty());
1027}
1028
1029void
1030CommandInterpreter::BuildAliasCommandArgs
1031(
1032 CommandObject *alias_cmd_obj,
1033 const char *alias_name,
1034 Args &cmd_args,
1035 CommandReturnObject &result
1036)
1037{
1038 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1039
1040 if (option_arg_vector_sp.get())
1041 {
1042 // Make sure that the alias name is the 0th element in cmd_args
1043 std::string alias_name_str = alias_name;
1044 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
1045 cmd_args.Unshift (alias_name);
1046
1047 Args new_args (alias_cmd_obj->GetCommandName());
1048 if (new_args.GetArgumentCount() == 2)
1049 new_args.Shift();
1050
1051 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1052 int old_size = cmd_args.GetArgumentCount();
1053 int *used = (int *) malloc ((old_size + 1) * sizeof (int));
1054
1055 memset (used, 0, (old_size + 1) * sizeof (int));
1056 used[0] = 1;
1057
1058 for (int i = 0; i < option_arg_vector->size(); ++i)
1059 {
1060 OptionArgPair option_pair = (*option_arg_vector)[i];
1061 std::string option = option_pair.first;
1062 std::string value = option_pair.second;
1063 if (option.compare ("<argument>") == 0)
1064 new_args.AppendArgument (value.c_str());
1065 else
1066 {
1067 new_args.AppendArgument (option.c_str());
1068 if (value.compare ("<no-argument>") != 0)
1069 {
1070 int index = GetOptionArgumentPosition (value.c_str());
1071 if (index == 0)
1072 // value was NOT a positional argument; must be a real value
1073 new_args.AppendArgument (value.c_str());
1074 else if (index >= cmd_args.GetArgumentCount())
1075 {
1076 result.AppendErrorWithFormat
1077 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
1078 index);
1079 result.SetStatus (eReturnStatusFailed);
1080 return;
1081 }
1082 else
1083 {
1084 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
1085 used[index] = 1;
1086 }
1087 }
1088 }
1089 }
1090
1091 for (int j = 0; j < cmd_args.GetArgumentCount(); ++j)
1092 {
1093 if (!used[j])
1094 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
1095 }
1096
1097 cmd_args.Clear();
1098 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
1099 }
1100 else
1101 {
1102 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1103 // This alias was not created with any options; nothing further needs to be done.
1104 return;
1105 }
1106
1107 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1108 return;
1109}
1110
1111
1112int
1113CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
1114{
1115 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
1116 // of zero.
1117
1118 char *cptr = (char *) in_string;
1119
1120 // Does it start with '%'
1121 if (cptr[0] == '%')
1122 {
1123 ++cptr;
1124
1125 // Is the rest of it entirely digits?
1126 if (isdigit (cptr[0]))
1127 {
1128 const char *start = cptr;
1129 while (isdigit (cptr[0]))
1130 ++cptr;
1131
1132 // We've gotten to the end of the digits; are we at the end of the string?
1133 if (cptr[0] == '\0')
1134 position = atoi (start);
1135 }
1136 }
1137
1138 return position;
1139}
1140
1141void
1142CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
1143{
1144 const char *init_file_path = in_cwd ? "./.lldbinit" : "~/.lldbinit";
1145 FileSpec init_file (init_file_path);
1146 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
1147 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
1148
1149 if (init_file.Exists())
1150 {
1151 char path[PATH_MAX];
1152 init_file.GetPath(path, sizeof(path));
1153 StreamString source_command;
Johnny Chen7c984242010-07-28 21:16:11 +00001154 source_command.Printf ("command source '%s'", path);
Chris Lattner24943d22010-06-08 16:52:24 +00001155 HandleCommand (source_command.GetData(), false, result);
1156 }
1157 else
1158 {
1159 // nothing to be done if the file doesn't exist
1160 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1161 }
1162}
1163
1164ScriptInterpreter *
1165CommandInterpreter::GetScriptInterpreter ()
1166{
Greg Clayton63094e02010-06-23 01:19:29 +00001167 CommandObject::CommandMap::iterator pos;
1168
1169 pos = m_command_dict.find ("script");
1170 if (pos != m_command_dict.end())
Chris Lattner24943d22010-06-08 16:52:24 +00001171 {
Greg Clayton63094e02010-06-23 01:19:29 +00001172 CommandObject *script_cmd_obj = pos->second.get();
1173 return ((CommandObjectScript *) script_cmd_obj)->GetInterpreter (*this);
Chris Lattner24943d22010-06-08 16:52:24 +00001174 }
Greg Clayton63094e02010-06-23 01:19:29 +00001175 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +00001176}
1177
1178
1179
1180bool
1181CommandInterpreter::GetSynchronous ()
1182{
1183 return m_synchronous_execution;
1184}
1185
1186void
1187CommandInterpreter::SetSynchronous (bool value)
1188{
1189 static bool value_set_once = false;
1190 if (!value_set_once)
1191 {
1192 value_set_once = true;
1193 m_synchronous_execution = value;
1194 }
1195}
1196
1197void
1198CommandInterpreter::OutputFormattedHelpText (Stream &strm,
1199 const char *word_text,
1200 const char *separator,
1201 const char *help_text,
1202 uint32_t max_word_len)
1203{
1204 StateVariable *var = GetStateVariable ("term-width");
1205 int max_columns = var->GetIntValue();
1206 // Sanity check max_columns, to cope with emacs shell mode with TERM=dumb
1207 // (0 rows; 0 columns;).
1208 if (max_columns <= 0) max_columns = 80;
1209
1210 int indent_size = max_word_len + strlen (separator) + 2;
1211
1212 strm.IndentMore (indent_size);
1213
1214 int len = indent_size + strlen (help_text) + 1;
1215 char *text = (char *) malloc (len);
1216 sprintf (text, "%-*s %s %s", max_word_len, word_text, separator, help_text);
1217 if (text[len - 1] == '\n')
1218 text[--len] = '\0';
1219
1220 if (len < max_columns)
1221 {
1222 // Output it as a single line.
1223 strm.Printf ("%s", text);
1224 }
1225 else
1226 {
1227 // We need to break it up into multiple lines.
1228 bool first_line = true;
1229 int text_width;
1230 int start = 0;
1231 int end = start;
1232 int final_end = strlen (text);
1233 int sub_len;
1234
1235 while (end < final_end)
1236 {
1237 if (first_line)
1238 text_width = max_columns - 1;
1239 else
1240 text_width = max_columns - indent_size - 1;
1241
1242 // Don't start the 'text' on a space, since we're already outputting the indentation.
1243 if (!first_line)
1244 {
1245 while ((start < final_end) && (text[start] == ' '))
1246 start++;
1247 }
1248
1249 end = start + text_width;
1250 if (end > final_end)
1251 end = final_end;
1252 else
1253 {
1254 // If we're not at the end of the text, make sure we break the line on white space.
1255 while (end > start
1256 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
1257 end--;
1258 }
1259
1260 sub_len = end - start;
1261 if (start != 0)
1262 strm.EOL();
1263 if (!first_line)
1264 strm.Indent();
1265 else
1266 first_line = false;
1267 assert (start <= final_end);
1268 assert (start + sub_len <= final_end);
1269 if (sub_len > 0)
1270 strm.Write (text + start, sub_len);
1271 start = end + 1;
1272 }
1273 }
1274 strm.EOL();
1275 strm.IndentLess(indent_size);
1276 free (text);
1277}
1278
1279void
1280CommandInterpreter::AproposAllSubCommands (CommandObject *cmd_obj, const char *prefix, const char *search_word,
1281 StringList &commands_found, StringList &commands_help)
1282{
1283 CommandObject::CommandMap::const_iterator pos;
1284 CommandObject::CommandMap sub_cmd_dict = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict;
1285 CommandObject *sub_cmd_obj;
1286
1287 for (pos = sub_cmd_dict.begin(); pos != sub_cmd_dict.end(); ++pos)
1288 {
1289 const char * command_name = pos->first.c_str();
1290 sub_cmd_obj = pos->second.get();
1291 StreamString complete_command_name;
1292
1293 complete_command_name.Printf ("%s %s", prefix, command_name);
1294
1295 if (sub_cmd_obj->HelpTextContainsWord (search_word))
1296 {
1297 commands_found.AppendString (complete_command_name.GetData());
1298 commands_help.AppendString (sub_cmd_obj->GetHelp());
1299 }
1300
1301 if (sub_cmd_obj->IsMultiwordObject())
1302 AproposAllSubCommands (sub_cmd_obj, complete_command_name.GetData(), search_word, commands_found,
1303 commands_help);
1304 }
1305
1306}
1307
1308void
1309CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
1310 StringList &commands_help)
1311{
1312 CommandObject::CommandMap::const_iterator pos;
1313
1314 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
1315 {
1316 const char *command_name = pos->first.c_str();
1317 CommandObject *cmd_obj = pos->second.get();
1318
1319 if (cmd_obj->HelpTextContainsWord (search_word))
1320 {
1321 commands_found.AppendString (command_name);
1322 commands_help.AppendString (cmd_obj->GetHelp());
1323 }
1324
1325 if (cmd_obj->IsMultiwordObject())
1326 AproposAllSubCommands (cmd_obj, command_name, search_word, commands_found, commands_help);
1327
1328 }
1329}