blob: bcbd5f8bfcf318a0b58690a8e93daa2a42e9ef71 [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>
Caroline Ticebd5c63e2010-10-12 21:57:09 +000011#include <vector>
Chris Lattner24943d22010-06-08 16:52:24 +000012
13#include <getopt.h>
14#include <stdlib.h>
15
Greg Clayton5c28dd12011-06-23 17:59:56 +000016#include "CommandObjectScript.h"
Peter Collingbourne921fac02011-06-23 20:37:26 +000017#include "lldb/Interpreter/CommandObjectRegexCommand.h"
Greg Clayton5c28dd12011-06-23 17:59:56 +000018
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000019#include "../Commands/CommandObjectApropos.h"
20#include "../Commands/CommandObjectArgs.h"
21#include "../Commands/CommandObjectBreakpoint.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000022#include "../Commands/CommandObjectDisassemble.h"
23#include "../Commands/CommandObjectExpression.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000024#include "../Commands/CommandObjectFrame.h"
25#include "../Commands/CommandObjectHelp.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000026#include "../Commands/CommandObjectLog.h"
27#include "../Commands/CommandObjectMemory.h"
Greg Claytonb1888f22011-03-19 01:12:21 +000028#include "../Commands/CommandObjectPlatform.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000029#include "../Commands/CommandObjectProcess.h"
30#include "../Commands/CommandObjectQuit.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000031#include "../Commands/CommandObjectRegister.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000032#include "../Commands/CommandObjectSettings.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000033#include "../Commands/CommandObjectSource.h"
Jim Ingham767af882010-07-07 03:36:20 +000034#include "../Commands/CommandObjectCommands.h"
Eli Friedmanccdb9ec2010-06-13 02:17:17 +000035#include "../Commands/CommandObjectSyntax.h"
36#include "../Commands/CommandObjectTarget.h"
37#include "../Commands/CommandObjectThread.h"
Greg Clayton5c28dd12011-06-23 17:59:56 +000038#include "../Commands/CommandObjectType.h"
Johnny Chen902e0182010-12-23 20:21:44 +000039#include "../Commands/CommandObjectVersion.h"
Chris Lattner24943d22010-06-08 16:52:24 +000040
Jim Ingham84cdc152010-06-15 19:49:27 +000041#include "lldb/Interpreter/Args.h"
Caroline Tice5ddbe212011-05-06 21:37:15 +000042#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000043#include "lldb/Core/Debugger.h"
Jim Ingham5e16ef52010-10-04 19:49:29 +000044#include "lldb/Core/InputReader.h"
Chris Lattner24943d22010-06-08 16:52:24 +000045#include "lldb/Core/Stream.h"
46#include "lldb/Core/Timer.h"
Greg Claytoncd548032011-02-01 01:31:41 +000047#include "lldb/Host/Host.h"
Chris Lattner24943d22010-06-08 16:52:24 +000048#include "lldb/Target/Process.h"
49#include "lldb/Target/Thread.h"
50#include "lldb/Target/TargetList.h"
Greg Claytone98ac252010-11-10 04:57:04 +000051#include "lldb/Utility/CleanUp.h"
Chris Lattner24943d22010-06-08 16:52:24 +000052
53#include "lldb/Interpreter/CommandReturnObject.h"
54#include "lldb/Interpreter/CommandInterpreter.h"
Caroline Tice0aa2e552011-01-14 00:29:16 +000055#include "lldb/Interpreter/ScriptInterpreterNone.h"
56#include "lldb/Interpreter/ScriptInterpreterPython.h"
Chris Lattner24943d22010-06-08 16:52:24 +000057
58using namespace lldb;
59using namespace lldb_private;
60
61CommandInterpreter::CommandInterpreter
62(
Greg Clayton63094e02010-06-23 01:19:29 +000063 Debugger &debugger,
Chris Lattner24943d22010-06-08 16:52:24 +000064 ScriptLanguage script_language,
Greg Clayton63094e02010-06-23 01:19:29 +000065 bool synchronous_execution
Chris Lattner24943d22010-06-08 16:52:24 +000066) :
Greg Clayton49ce6822010-10-31 03:01:06 +000067 Broadcaster ("lldb.command-interpreter"),
Greg Clayton63094e02010-06-23 01:19:29 +000068 m_debugger (debugger),
Greg Clayton887aa282010-10-11 01:05:37 +000069 m_synchronous_execution (synchronous_execution),
Caroline Tice0aa2e552011-01-14 00:29:16 +000070 m_skip_lldbinit_files (false),
Jim Ingham949d5ac2011-02-18 00:54:25 +000071 m_script_interpreter_ap (),
Caroline Tice892fadd2011-06-16 16:27:19 +000072 m_comment_char ('#'),
73 m_batch_command_mode (false)
Chris Lattner24943d22010-06-08 16:52:24 +000074{
Caroline Tice6e4c5ce2010-09-04 00:03:46 +000075 const char *dbg_name = debugger.GetInstanceName().AsCString();
76 std::string lang_name = ScriptInterpreter::LanguageToString (script_language);
77 StreamString var_name;
78 var_name.Printf ("[%s].script-lang", dbg_name);
Caroline Tice1d2aefd2010-09-09 06:25:08 +000079 debugger.GetSettingsController()->SetVariable (var_name.GetData(), lang_name.c_str(),
Greg Claytonb3448432011-03-24 21:19:54 +000080 eVarSetOperationAssign, false,
Greg Clayton49ce6822010-10-31 03:01:06 +000081 m_debugger.GetInstanceName().AsCString());
82 SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
83 SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
84 SetEventName (eBroadcastBitQuitCommandReceived, "quit");
Chris Lattner24943d22010-06-08 16:52:24 +000085}
86
87void
88CommandInterpreter::Initialize ()
89{
90 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
91
92 CommandReturnObject result;
93
94 LoadCommandDictionary ();
95
Chris Lattner24943d22010-06-08 16:52:24 +000096 // Set up some initial aliases.
Caroline Tice5ddbe212011-05-06 21:37:15 +000097 CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
98 if (cmd_obj_sp)
99 {
100 AddAlias ("q", cmd_obj_sp);
101 AddAlias ("exit", cmd_obj_sp);
102 }
103
104 cmd_obj_sp = GetCommandSPExact ("process continue", false);
105 if (cmd_obj_sp)
106 {
107 AddAlias ("c", cmd_obj_sp);
108 AddAlias ("continue", cmd_obj_sp);
109 }
110
111 cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
112 if (cmd_obj_sp)
113 AddAlias ("b", cmd_obj_sp);
114
115 cmd_obj_sp = GetCommandSPExact ("thread backtrace", false);
116 if (cmd_obj_sp)
117 AddAlias ("bt", cmd_obj_sp);
118
119 cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
120 if (cmd_obj_sp)
121 AddAlias ("si", cmd_obj_sp);
122
123 cmd_obj_sp = GetCommandSPExact ("thread step-in", false);
124 if (cmd_obj_sp)
125 {
126 AddAlias ("s", cmd_obj_sp);
127 AddAlias ("step", cmd_obj_sp);
128 }
129
130 cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
131 if (cmd_obj_sp)
132 {
133 AddAlias ("n", cmd_obj_sp);
134 AddAlias ("next", cmd_obj_sp);
135 }
136
137 cmd_obj_sp = GetCommandSPExact ("thread step-out", false);
138 if (cmd_obj_sp)
139 {
140 AddAlias ("f", cmd_obj_sp);
141 AddAlias ("finish", cmd_obj_sp);
142 }
143
144 cmd_obj_sp = GetCommandSPExact ("source list", false);
145 if (cmd_obj_sp)
146 {
147 AddAlias ("l", cmd_obj_sp);
148 AddAlias ("list", cmd_obj_sp);
149 }
150
151 cmd_obj_sp = GetCommandSPExact ("memory read", false);
152 if (cmd_obj_sp)
153 AddAlias ("x", cmd_obj_sp);
154
155 cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
156 if (cmd_obj_sp)
157 AddAlias ("up", cmd_obj_sp);
158
159 cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
160 if (cmd_obj_sp)
161 AddAlias ("down", cmd_obj_sp);
162
163 cmd_obj_sp = GetCommandSPExact ("target create", false);
164 if (cmd_obj_sp)
165 AddAlias ("file", cmd_obj_sp);
166
167 cmd_obj_sp = GetCommandSPExact ("target modules", false);
168 if (cmd_obj_sp)
169 AddAlias ("image", cmd_obj_sp);
170
171
172 OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
Jim Inghame56493f2011-03-22 02:29:32 +0000173
Caroline Tice5ddbe212011-05-06 21:37:15 +0000174 cmd_obj_sp = GetCommandSPExact ("expression", false);
175 if (cmd_obj_sp)
176 {
177 AddAlias ("expr", cmd_obj_sp);
178
179 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
180 AddAlias ("p", cmd_obj_sp);
181 AddAlias ("print", cmd_obj_sp);
182 AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp);
183 AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp);
184
185 alias_arguments_vector_sp.reset (new OptionArgVector);
186 ProcessAliasOptionsArgs (cmd_obj_sp, "-o --", alias_arguments_vector_sp);
187 AddAlias ("po", cmd_obj_sp);
188 AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
189 }
190
191 cmd_obj_sp = GetCommandSPExact ("process launch", false);
192 if (cmd_obj_sp)
193 {
194 alias_arguments_vector_sp.reset (new OptionArgVector);
195 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
196 AddAlias ("r", cmd_obj_sp);
197 AddAlias ("run", cmd_obj_sp);
198 AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp);
199 AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp);
200 }
201
Chris Lattner24943d22010-06-08 16:52:24 +0000202}
203
Chris Lattner24943d22010-06-08 16:52:24 +0000204const char *
205CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
206{
207 // This function has not yet been implemented.
208
209 // Look for any embedded script command
210 // If found,
211 // get interpreter object from the command dictionary,
212 // call execute_one_command on it,
213 // get the results as a string,
214 // substitute that string for current stuff.
215
216 return arg;
217}
218
219
220void
221CommandInterpreter::LoadCommandDictionary ()
222{
223 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
224
225 // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
226 //
227 // Command objects that are used as cross reference objects (i.e. they inherit from CommandObjectCrossref)
228 // *MUST* be created and put into the command dictionary *BEFORE* any multi-word commands (which may use
229 // the cross-referencing stuff) are created!!!
230 //
231 // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
232
233
234 // Command objects that inherit from CommandObjectCrossref must be created before other command objects
235 // are created. This is so that when another command is created that needs to go into a crossref object,
236 // the crossref object exists and is ready to take the cross reference. Put the cross referencing command
237 // objects into the CommandDictionary now, so they are ready for use when the other commands get created.
238
Chris Lattner24943d22010-06-08 16:52:24 +0000239 // Non-CommandObjectCrossref commands can now be created.
240
Caroline Tice5bc8c972010-09-20 20:44:43 +0000241 lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000242
Greg Clayton238c0a12010-09-18 01:14:36 +0000243 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000244 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
Greg Clayton238c0a12010-09-18 01:14:36 +0000245 //m_command_dict["call"] = CommandObjectSP (new CommandObjectCall (*this));
Johnny Chen9e4c3d72011-04-21 00:39:18 +0000246 m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
Greg Clayton238c0a12010-09-18 01:14:36 +0000247 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
248 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
Greg Claytonabe0fed2011-04-18 08:33:37 +0000249// m_command_dict["file"] = CommandObjectSP (new CommandObjectFile (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000250 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
Greg Clayton238c0a12010-09-18 01:14:36 +0000251 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this));
Greg Claytone1f50b92011-05-03 22:09:39 +0000252 /// m_command_dict["image"] = CommandObjectSP (new CommandObjectImage (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000253 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this));
254 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this));
Greg Claytonb1888f22011-03-19 01:12:21 +0000255 m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000256 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
Greg Clayton238c0a12010-09-18 01:14:36 +0000257 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000258 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this));
Greg Clayton238c0a12010-09-18 01:14:36 +0000259 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language));
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000260 m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
Jim Ingham767af882010-07-07 03:36:20 +0000261 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000262 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
263 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this));
Greg Clayton5c28dd12011-06-23 17:59:56 +0000264 m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this));
Johnny Chen902e0182010-12-23 20:21:44 +0000265 m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this));
Chris Lattner24943d22010-06-08 16:52:24 +0000266
267 std::auto_ptr<CommandObjectRegexCommand>
Greg Clayton238c0a12010-09-18 01:14:36 +0000268 break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Claytonb72d0f02011-04-12 05:54:46 +0000269 "_regexp-break",
Caroline Ticec1ad82e2010-09-07 22:38:08 +0000270 "Set a breakpoint using a regular expression to specify the location.",
Greg Claytonb72d0f02011-04-12 05:54:46 +0000271 "_regexp-break [<filename>:<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 2));
Chris Lattner24943d22010-06-08 16:52:24 +0000272 if (break_regex_cmd_ap.get())
273 {
274 if (break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2") &&
275 break_regex_cmd_ap->AddRegexCommand("^(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1") &&
276 break_regex_cmd_ap->AddRegexCommand("^[\"']?([-+]\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'") &&
Greg Claytonb72d0f02011-04-12 05:54:46 +0000277 break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full") &&
Chris Lattner24943d22010-06-08 16:52:24 +0000278 break_regex_cmd_ap->AddRegexCommand("^(-.*)$", "breakpoint set %1") &&
Greg Claytonb01000f2011-01-17 03:46:26 +0000279 break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'") &&
Chris Lattner24943d22010-06-08 16:52:24 +0000280 break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"))
281 {
282 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
283 m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
284 }
285 }
Jim Inghame56493f2011-03-22 02:29:32 +0000286
287 std::auto_ptr<CommandObjectRegexCommand>
288 down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Claytonb72d0f02011-04-12 05:54:46 +0000289 "_regexp-down",
290 "Go down \"n\" frames in the stack (1 frame by default).",
291 "_regexp-down [n]", 2));
Jim Inghame56493f2011-03-22 02:29:32 +0000292 if (down_regex_cmd_ap.get())
293 {
294 if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
295 down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1"))
296 {
297 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
298 m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
299 }
300 }
301
302 std::auto_ptr<CommandObjectRegexCommand>
303 up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Claytonb72d0f02011-04-12 05:54:46 +0000304 "_regexp-up",
305 "Go up \"n\" frames in the stack (1 frame by default).",
306 "_regexp-up [n]", 2));
Jim Inghame56493f2011-03-22 02:29:32 +0000307 if (up_regex_cmd_ap.get())
308 {
309 if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
310 up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1"))
311 {
312 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
313 m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp;
314 }
315 }
Chris Lattner24943d22010-06-08 16:52:24 +0000316}
317
318int
319CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
320 StringList &matches)
321{
322 CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
323
324 if (include_aliases)
325 {
326 CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
327 }
328
329 return matches.GetSize();
330}
331
332CommandObjectSP
333CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
334{
335 CommandObject::CommandMap::iterator pos;
336 CommandObjectSP ret_val;
337
338 std::string cmd(cmd_cstr);
339
340 if (HasCommands())
341 {
342 pos = m_command_dict.find(cmd);
343 if (pos != m_command_dict.end())
344 ret_val = pos->second;
345 }
346
347 if (include_aliases && HasAliases())
348 {
349 pos = m_alias_dict.find(cmd);
350 if (pos != m_alias_dict.end())
351 ret_val = pos->second;
352 }
353
354 if (HasUserCommands())
355 {
356 pos = m_user_dict.find(cmd);
357 if (pos != m_user_dict.end())
358 ret_val = pos->second;
359 }
360
361 if (!exact && ret_val == NULL)
362 {
Jim Inghamd40f8a62010-07-06 22:46:59 +0000363 // We will only get into here if we didn't find any exact matches.
364
365 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
366
Chris Lattner24943d22010-06-08 16:52:24 +0000367 StringList local_matches;
368 if (matches == NULL)
369 matches = &local_matches;
370
Jim Inghamd40f8a62010-07-06 22:46:59 +0000371 unsigned int num_cmd_matches = 0;
372 unsigned int num_alias_matches = 0;
373 unsigned int num_user_matches = 0;
374
375 // Look through the command dictionaries one by one, and if we get only one match from any of
376 // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
377
Chris Lattner24943d22010-06-08 16:52:24 +0000378 if (HasCommands())
379 {
380 num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
381 }
382
383 if (num_cmd_matches == 1)
384 {
385 cmd.assign(matches->GetStringAtIndex(0));
386 pos = m_command_dict.find(cmd);
387 if (pos != m_command_dict.end())
Jim Inghamd40f8a62010-07-06 22:46:59 +0000388 real_match_sp = pos->second;
Chris Lattner24943d22010-06-08 16:52:24 +0000389 }
390
Jim Ingham9a574172010-06-24 20:28:42 +0000391 if (include_aliases && HasAliases())
Chris Lattner24943d22010-06-08 16:52:24 +0000392 {
393 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
394
395 }
396
Jim Inghamd40f8a62010-07-06 22:46:59 +0000397 if (num_alias_matches == 1)
Chris Lattner24943d22010-06-08 16:52:24 +0000398 {
399 cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
400 pos = m_alias_dict.find(cmd);
401 if (pos != m_alias_dict.end())
Jim Inghamd40f8a62010-07-06 22:46:59 +0000402 alias_match_sp = pos->second;
Chris Lattner24943d22010-06-08 16:52:24 +0000403 }
404
Jim Ingham9a574172010-06-24 20:28:42 +0000405 if (HasUserCommands())
Chris Lattner24943d22010-06-08 16:52:24 +0000406 {
407 num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
408 }
409
Jim Inghamd40f8a62010-07-06 22:46:59 +0000410 if (num_user_matches == 1)
Chris Lattner24943d22010-06-08 16:52:24 +0000411 {
412 cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
413
414 pos = m_user_dict.find (cmd);
415 if (pos != m_user_dict.end())
Jim Inghamd40f8a62010-07-06 22:46:59 +0000416 user_match_sp = pos->second;
417 }
418
419 // If we got exactly one match, return that, otherwise return the match list.
420
421 if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
422 {
423 if (num_cmd_matches)
424 return real_match_sp;
425 else if (num_alias_matches)
426 return alias_match_sp;
427 else
428 return user_match_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000429 }
430 }
Jim Inghamd40f8a62010-07-06 22:46:59 +0000431 else if (matches && ret_val != NULL)
432 {
433 matches->AppendString (cmd_cstr);
Chris Lattner24943d22010-06-08 16:52:24 +0000434 }
435
436
437 return ret_val;
438}
439
Greg Claytond12aeab2011-04-20 16:37:46 +0000440bool
441CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
442{
443 if (name && name[0])
444 {
445 std::string name_sstr(name);
446 if (!can_replace)
447 {
448 if (m_command_dict.find (name_sstr) != m_command_dict.end())
449 return false;
450 }
451 m_command_dict[name_sstr] = cmd_sp;
452 return true;
453 }
454 return false;
455}
456
457
Jim Inghamd40f8a62010-07-06 22:46:59 +0000458CommandObjectSP
459CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
Chris Lattner24943d22010-06-08 16:52:24 +0000460{
Caroline Tice56d2fc42010-12-14 18:51:39 +0000461 Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
462 CommandObjectSP ret_val; // Possibly empty return value.
463
464 if (cmd_cstr == NULL)
465 return ret_val;
466
467 if (cmd_words.GetArgumentCount() == 1)
468 return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
469 else
470 {
471 // We have a multi-word command (seemingly), so we need to do more work.
472 // First, get the cmd_obj_sp for the first word in the command.
473 CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL);
474 if (cmd_obj_sp.get() != NULL)
475 {
476 // Loop through the rest of the words in the command (everything passed in was supposed to be part of a
477 // command name), and find the appropriate sub-command SP for each command word....
478 size_t end = cmd_words.GetArgumentCount();
479 for (size_t j= 1; j < end; ++j)
480 {
481 if (cmd_obj_sp->IsMultiwordObject())
482 {
483 cmd_obj_sp = ((CommandObjectMultiword *) cmd_obj_sp.get())->GetSubcommandSP
484 (cmd_words.GetArgumentAtIndex (j));
485 if (cmd_obj_sp.get() == NULL)
486 // The sub-command name was invalid. Fail and return the empty 'ret_val'.
487 return ret_val;
488 }
489 else
490 // We have more words in the command name, but we don't have a multiword object. Fail and return
491 // empty 'ret_val'.
492 return ret_val;
493 }
494 // We successfully looped through all the command words and got valid command objects for them. Assign the
495 // last object retrieved to 'ret_val'.
496 ret_val = cmd_obj_sp;
497 }
498 }
499 return ret_val;
Jim Inghamd40f8a62010-07-06 22:46:59 +0000500}
501
502CommandObject *
503CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
504{
505 return GetCommandSPExact (cmd_cstr, include_aliases).get();
506}
507
508CommandObject *
509CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
510{
511 CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
512
513 // If we didn't find an exact match to the command string in the commands, look in
514 // the aliases.
515
516 if (command_obj == NULL)
517 {
518 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
519 }
520
521 // Finally, if there wasn't an exact match among the aliases, look for an inexact match
522 // in both the commands and the aliases.
523
524 if (command_obj == NULL)
525 command_obj = GetCommandSP(cmd_cstr, true, false, matches).get();
526
527 return command_obj;
Chris Lattner24943d22010-06-08 16:52:24 +0000528}
529
530bool
531CommandInterpreter::CommandExists (const char *cmd)
532{
533 return m_command_dict.find(cmd) != m_command_dict.end();
534}
535
536bool
Caroline Tice5ddbe212011-05-06 21:37:15 +0000537CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
538 const char *options_args,
539 OptionArgVectorSP &option_arg_vector_sp)
540{
541 bool success = true;
542 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
543
544 if (!options_args || (strlen (options_args) < 1))
545 return true;
546
547 std::string options_string (options_args);
548 Args args (options_args);
549 CommandReturnObject result;
550 // Check to see if the command being aliased can take any command options.
551 Options *options = cmd_obj_sp->GetOptions ();
552 if (options)
553 {
554 // See if any options were specified as part of the alias; if so, handle them appropriately.
555 options->NotifyOptionParsingStarting ();
556 args.Unshift ("dummy_arg");
557 args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
558 args.Shift ();
559 if (result.Succeeded())
560 options->VerifyPartialOptions (result);
561 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
562 {
563 result.AppendError ("Unable to create requested alias.\n");
564 return false;
565 }
566 }
567
568 if (options_string.size() > 0)
569 {
570 if (cmd_obj_sp->WantsRawCommandString ())
571 option_arg_vector->push_back (OptionArgPair ("<argument>",
572 OptionArgValue (-1,
573 options_string)));
574 else
575 {
576 int argc = args.GetArgumentCount();
577 for (size_t i = 0; i < argc; ++i)
578 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
579 option_arg_vector->push_back
580 (OptionArgPair ("<argument>",
581 OptionArgValue (-1,
582 std::string (args.GetArgumentAtIndex (i)))));
583 }
584 }
585
586 return success;
587}
588
589bool
Chris Lattner24943d22010-06-08 16:52:24 +0000590CommandInterpreter::AliasExists (const char *cmd)
591{
592 return m_alias_dict.find(cmd) != m_alias_dict.end();
593}
594
595bool
596CommandInterpreter::UserCommandExists (const char *cmd)
597{
598 return m_user_dict.find(cmd) != m_user_dict.end();
599}
600
601void
602CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
603{
Jim Inghamd40f8a62010-07-06 22:46:59 +0000604 command_obj_sp->SetIsAlias (true);
Chris Lattner24943d22010-06-08 16:52:24 +0000605 m_alias_dict[alias_name] = command_obj_sp;
606}
607
608bool
609CommandInterpreter::RemoveAlias (const char *alias_name)
610{
611 CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
612 if (pos != m_alias_dict.end())
613 {
614 m_alias_dict.erase(pos);
615 return true;
616 }
617 return false;
618}
619bool
620CommandInterpreter::RemoveUser (const char *alias_name)
621{
622 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
623 if (pos != m_user_dict.end())
624 {
625 m_user_dict.erase(pos);
626 return true;
627 }
628 return false;
629}
630
Chris Lattner24943d22010-06-08 16:52:24 +0000631void
632CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
633{
634 help_string.Printf ("'%s", command_name);
635 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
636
637 if (option_arg_vector_sp != NULL)
638 {
639 OptionArgVector *options = option_arg_vector_sp.get();
640 for (int i = 0; i < options->size(); ++i)
641 {
642 OptionArgPair cur_option = (*options)[i];
643 std::string opt = cur_option.first;
Caroline Tice44c841d2010-12-07 19:58:26 +0000644 OptionArgValue value_pair = cur_option.second;
645 std::string value = value_pair.second;
Chris Lattner24943d22010-06-08 16:52:24 +0000646 if (opt.compare("<argument>") == 0)
647 {
648 help_string.Printf (" %s", value.c_str());
649 }
650 else
651 {
652 help_string.Printf (" %s", opt.c_str());
653 if ((value.compare ("<no-argument>") != 0)
654 && (value.compare ("<need-argument") != 0))
655 {
656 help_string.Printf (" %s", value.c_str());
657 }
658 }
659 }
660 }
661
662 help_string.Printf ("'");
663}
664
Greg Clayton65124ea2010-08-26 22:05:43 +0000665size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000666CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
667{
668 CommandObject::CommandMap::const_iterator pos;
Greg Clayton65124ea2010-08-26 22:05:43 +0000669 CommandObject::CommandMap::const_iterator end = dict.end();
670 size_t max_len = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000671
Greg Clayton65124ea2010-08-26 22:05:43 +0000672 for (pos = dict.begin(); pos != end; ++pos)
673 {
674 size_t len = pos->first.size();
675 if (max_len < len)
676 max_len = len;
Chris Lattner24943d22010-06-08 16:52:24 +0000677 }
Greg Clayton65124ea2010-08-26 22:05:43 +0000678 return max_len;
Chris Lattner24943d22010-06-08 16:52:24 +0000679}
680
681void
682CommandInterpreter::GetHelp (CommandReturnObject &result)
683{
684 CommandObject::CommandMap::const_iterator pos;
685 result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
686 result.AppendMessage("");
Greg Clayton65124ea2010-08-26 22:05:43 +0000687 uint32_t max_len = FindLongestCommandWord (m_command_dict);
Chris Lattner24943d22010-06-08 16:52:24 +0000688
689 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
690 {
691 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
692 max_len);
693 }
694 result.AppendMessage("");
695
696 if (m_alias_dict.size() > 0)
697 {
Jim Inghame3663e82010-10-22 18:47:16 +0000698 result.AppendMessage("The following is a list of your current command abbreviations "
Johnny Chen9e4c3d72011-04-21 00:39:18 +0000699 "(see 'help command alias' for more info):");
Chris Lattner24943d22010-06-08 16:52:24 +0000700 result.AppendMessage("");
Greg Clayton65124ea2010-08-26 22:05:43 +0000701 max_len = FindLongestCommandWord (m_alias_dict);
702
Chris Lattner24943d22010-06-08 16:52:24 +0000703 for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
704 {
705 StreamString sstr;
706 StreamString translation_and_help;
707 std::string entry_name = pos->first;
708 std::string second_entry = pos->second.get()->GetCommandName();
709 GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
710
711 translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp());
712 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
713 translation_and_help.GetData(), max_len);
714 }
715 result.AppendMessage("");
716 }
717
718 if (m_user_dict.size() > 0)
719 {
720 result.AppendMessage ("The following is a list of your current user-defined commands:");
721 result.AppendMessage("");
722 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
723 {
724 result.AppendMessageWithFormat ("%s -- %s\n", pos->first.c_str(), pos->second->GetHelp());
725 }
726 result.AppendMessage("");
727 }
728
729 result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
730}
731
Caroline Ticee0da7a52010-12-09 22:52:49 +0000732CommandObject *
733CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
Chris Lattner24943d22010-06-08 16:52:24 +0000734{
Caroline Ticee0da7a52010-12-09 22:52:49 +0000735 // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
736 // eventually be invoked by the given command line.
737
738 CommandObject *cmd_obj = NULL;
739 std::string white_space (" \t\v");
740 size_t start = command_string.find_first_not_of (white_space);
741 size_t end = 0;
742 bool done = false;
743 while (!done)
744 {
745 if (start != std::string::npos)
746 {
747 // Get the next word from command_string.
748 end = command_string.find_first_of (white_space, start);
749 if (end == std::string::npos)
750 end = command_string.size();
751 std::string cmd_word = command_string.substr (start, end - start);
752
753 if (cmd_obj == NULL)
754 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
755 // command or alias.
756 cmd_obj = GetCommandObject (cmd_word.c_str());
757 else if (cmd_obj->IsMultiwordObject ())
758 {
759 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
760 CommandObject *sub_cmd_obj =
761 ((CommandObjectMultiword *) cmd_obj)->GetSubcommandObject (cmd_word.c_str());
762 if (sub_cmd_obj)
763 cmd_obj = sub_cmd_obj;
764 else // cmd_word was not a valid sub-command word, so we are donee
765 done = true;
766 }
767 else
768 // We have a cmd_obj and it is not a multi-word object, so we are done.
769 done = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000770
Caroline Ticee0da7a52010-12-09 22:52:49 +0000771 // If we didn't find a valid command object, or our command object is not a multi-word object, or
772 // we are at the end of the command_string, then we are done. Otherwise, find the start of the
773 // next word.
774
775 if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
776 done = true;
777 else
778 start = command_string.find_first_not_of (white_space, end);
779 }
780 else
781 // Unable to find any more words.
782 done = true;
783 }
784
785 if (end == command_string.size())
786 command_string.clear();
787 else
788 command_string = command_string.substr(end);
789
790 return cmd_obj;
791}
792
793bool
Caroline Tice649116c2011-05-11 16:07:06 +0000794CommandInterpreter::StripFirstWord (std::string &command_string, std::string &word, bool &was_quoted, char &quote_char)
Caroline Ticee0da7a52010-12-09 22:52:49 +0000795{
796 std::string white_space (" \t\v");
797 size_t start;
798 size_t end;
799
800 start = command_string.find_first_not_of (white_space);
801 if (start != std::string::npos)
802 {
Caroline Tice649116c2011-05-11 16:07:06 +0000803 size_t len = command_string.size() - start;
804 if (len >= 2
805 && ((command_string[start] == '\'') || (command_string[start] == '"')))
Caroline Ticee0da7a52010-12-09 22:52:49 +0000806 {
Caroline Tice649116c2011-05-11 16:07:06 +0000807 was_quoted = true;
808 quote_char = command_string[start];
809 std::string quote_string = command_string.substr (start, 1);
810 start = start + 1;
811 end = command_string.find (quote_string, start);
812 if (end != std::string::npos)
813 {
814 word = command_string.substr (start, end - start);
815 if (end + 1 < len)
816 command_string = command_string.substr (end+1);
817 else
818 command_string.erase ();
819 size_t pos = command_string.find_first_not_of (white_space);
820 if ((pos != 0) && (pos != std::string::npos))
821 command_string = command_string.substr (pos);
822 }
823 else
824 {
825 word = command_string.substr (start - 1);
826 command_string.erase ();
827 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000828 }
829 else
830 {
Caroline Tice649116c2011-05-11 16:07:06 +0000831 end = command_string.find_first_of (white_space, start);
832 if (end != std::string::npos)
833 {
834 word = command_string.substr (start, end - start);
835 command_string = command_string.substr (end);
836 size_t pos = command_string.find_first_not_of (white_space);
837 if ((pos != 0) && (pos != std::string::npos))
838 command_string = command_string.substr (pos);
839 }
840 else
841 {
842 word = command_string.substr (start);
843 command_string.erase();
844 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000845 }
846
847 }
848 return true;
849}
850
851void
852CommandInterpreter::BuildAliasResult (const char *alias_name, std::string &raw_input_string, std::string &alias_result,
853 CommandObject *&alias_cmd_obj, CommandReturnObject &result)
854{
855 Args cmd_args (raw_input_string.c_str());
856 alias_cmd_obj = GetCommandObject (alias_name);
857 StreamString result_str;
858
859 if (alias_cmd_obj)
860 {
861 std::string alias_name_str = alias_name;
862 if ((cmd_args.GetArgumentCount() == 0)
863 || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
864 cmd_args.Unshift (alias_name);
865
866 result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
867 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
868
869 if (option_arg_vector_sp.get())
870 {
871 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
872
873 for (int i = 0; i < option_arg_vector->size(); ++i)
874 {
875 OptionArgPair option_pair = (*option_arg_vector)[i];
876 OptionArgValue value_pair = option_pair.second;
877 int value_type = value_pair.first;
878 std::string option = option_pair.first;
879 std::string value = value_pair.second;
880 if (option.compare ("<argument>") == 0)
881 result_str.Printf (" %s", value.c_str());
882 else
883 {
884 result_str.Printf (" %s", option.c_str());
885 if (value_type != optional_argument)
886 result_str.Printf (" ");
887 if (value.compare ("<no_argument>") != 0)
888 {
889 int index = GetOptionArgumentPosition (value.c_str());
890 if (index == 0)
891 result_str.Printf ("%s", value.c_str());
892 else if (index >= cmd_args.GetArgumentCount())
893 {
894
895 result.AppendErrorWithFormat
896 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
897 index);
898 result.SetStatus (eReturnStatusFailed);
899 return;
900 }
901 else
902 {
903 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
904 if (strpos != std::string::npos)
905 raw_input_string = raw_input_string.erase (strpos,
906 strlen (cmd_args.GetArgumentAtIndex (index)));
907 result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
908 }
909 }
910 }
911 }
912 }
913
914 alias_result = result_str.GetData();
915 }
916}
917
918bool
919CommandInterpreter::HandleCommand (const char *command_line,
920 bool add_to_history,
921 CommandReturnObject &result,
Jim Ingham949d5ac2011-02-18 00:54:25 +0000922 ExecutionContext *override_context,
923 bool repeat_on_empty_command)
924
Caroline Ticee0da7a52010-12-09 22:52:49 +0000925{
Jim Ingham949d5ac2011-02-18 00:54:25 +0000926
Caroline Ticee0da7a52010-12-09 22:52:49 +0000927 bool done = false;
928 CommandObject *cmd_obj = NULL;
929 std::string next_word;
930 bool wants_raw_input = false;
931 std::string command_string (command_line);
932
933 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
Greg Claytone98ac252010-11-10 04:57:04 +0000934 Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
935
936 // Make a scoped cleanup object that will clear the crash description string
937 // on exit of this function.
938 lldb_utility::CleanUp <const char *, void> crash_description_cleanup(NULL, Host::SetCrashDescription);
939
Caroline Ticee0da7a52010-12-09 22:52:49 +0000940 if (log)
941 log->Printf ("Processing command: %s", command_line);
Chris Lattner24943d22010-06-08 16:52:24 +0000942
Jim Inghamabab14b2010-11-04 23:08:45 +0000943 Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
944
Greg Claytonb72d0f02011-04-12 05:54:46 +0000945 UpdateExecutionContext (override_context);
Chris Lattner24943d22010-06-08 16:52:24 +0000946
Jim Ingham949d5ac2011-02-18 00:54:25 +0000947 bool empty_command = false;
948 bool comment_command = false;
949 if (command_string.empty())
950 empty_command = true;
951 else
Chris Lattner24943d22010-06-08 16:52:24 +0000952 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000953 const char *k_space_characters = "\t\n\v\f\r ";
954
955 size_t non_space = command_string.find_first_not_of (k_space_characters);
956 // Check for empty line or comment line (lines whose first
957 // non-space character is the comment character for this interpreter)
958 if (non_space == std::string::npos)
959 empty_command = true;
960 else if (command_string[non_space] == m_comment_char)
961 comment_command = true;
962 }
963
964 if (empty_command)
965 {
966 if (repeat_on_empty_command)
Chris Lattner24943d22010-06-08 16:52:24 +0000967 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000968 if (m_command_history.empty())
969 {
970 result.AppendError ("empty command");
971 result.SetStatus(eReturnStatusFailed);
972 return false;
973 }
974 else
975 {
976 command_line = m_repeat_command.c_str();
977 command_string = command_line;
978 if (m_repeat_command.empty())
979 {
980 result.AppendErrorWithFormat("No auto repeat.\n");
981 result.SetStatus (eReturnStatusFailed);
982 return false;
983 }
984 }
985 add_to_history = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000986 }
987 else
988 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000989 result.SetStatus (eReturnStatusSuccessFinishNoResult);
990 return true;
Chris Lattner24943d22010-06-08 16:52:24 +0000991 }
Jim Ingham949d5ac2011-02-18 00:54:25 +0000992 }
993 else if (comment_command)
994 {
995 result.SetStatus (eReturnStatusSuccessFinishNoResult);
996 return true;
Chris Lattner24943d22010-06-08 16:52:24 +0000997 }
Caroline Tice649116c2011-05-11 16:07:06 +0000998
Caroline Ticee0da7a52010-12-09 22:52:49 +0000999 // Phase 1.
1000
1001 // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
1002 // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that
1003 // the user could have specified an alias, and in translating the alias there may also be command options and/or
1004 // even data (including raw text strings) that need to be found and inserted into the command line as part of
1005 // the translation. So this first step is plain look-up & replacement, resulting in three things: 1). the command
Greg Clayton5d187e52011-01-08 20:28:42 +00001006 // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
Caroline Ticee0da7a52010-12-09 22:52:49 +00001007 // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
Caroline Tice44c841d2010-12-07 19:58:26 +00001008
Caroline Ticee0da7a52010-12-09 22:52:49 +00001009 StreamString revised_command_line;
Caroline Ticeea6e3df2010-12-11 08:16:56 +00001010 size_t actual_cmd_name_len = 0;
Caroline Ticee0da7a52010-12-09 22:52:49 +00001011 while (!done)
Chris Lattner24943d22010-06-08 16:52:24 +00001012 {
Caroline Tice649116c2011-05-11 16:07:06 +00001013 bool was_quoted = false;
1014 char quote_char = '\0';
1015 StripFirstWord (command_string, next_word, was_quoted, quote_char);
Caroline Ticee0da7a52010-12-09 22:52:49 +00001016 if (!cmd_obj && AliasExists (next_word.c_str()))
Chris Lattner24943d22010-06-08 16:52:24 +00001017 {
Caroline Ticee0da7a52010-12-09 22:52:49 +00001018 std::string alias_result;
1019 BuildAliasResult (next_word.c_str(), command_string, alias_result, cmd_obj, result);
1020 revised_command_line.Printf ("%s", alias_result.c_str());
1021 if (cmd_obj)
Caroline Tice56d2fc42010-12-14 18:51:39 +00001022 {
Caroline Ticee0da7a52010-12-09 22:52:49 +00001023 wants_raw_input = cmd_obj->WantsRawCommandString ();
Caroline Tice56d2fc42010-12-14 18:51:39 +00001024 actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
1025 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001026 }
1027 else if (!cmd_obj)
1028 {
1029 cmd_obj = GetCommandObject (next_word.c_str());
1030 if (cmd_obj)
Chris Lattner24943d22010-06-08 16:52:24 +00001031 {
Caroline Ticeea6e3df2010-12-11 08:16:56 +00001032 actual_cmd_name_len += next_word.length();
Caroline Ticee0da7a52010-12-09 22:52:49 +00001033 revised_command_line.Printf ("%s", next_word.c_str());
1034 wants_raw_input = cmd_obj->WantsRawCommandString ();
Chris Lattner24943d22010-06-08 16:52:24 +00001035 }
1036 else
1037 {
Caroline Ticee0da7a52010-12-09 22:52:49 +00001038 revised_command_line.Printf ("%s", next_word.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001039 }
1040 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001041 else if (cmd_obj->IsMultiwordObject ())
1042 {
1043 CommandObject *sub_cmd_obj = ((CommandObjectMultiword *) cmd_obj)->GetSubcommandObject (next_word.c_str());
1044 if (sub_cmd_obj)
1045 {
Caroline Ticeea6e3df2010-12-11 08:16:56 +00001046 actual_cmd_name_len += next_word.length() + 1;
Caroline Ticee0da7a52010-12-09 22:52:49 +00001047 revised_command_line.Printf (" %s", next_word.c_str());
1048 cmd_obj = sub_cmd_obj;
1049 wants_raw_input = cmd_obj->WantsRawCommandString ();
1050 }
1051 else
1052 {
Caroline Tice649116c2011-05-11 16:07:06 +00001053 if (was_quoted)
1054 {
1055 if (quote_char == '"')
1056 revised_command_line.Printf (" \"%s\"", next_word.c_str());
1057 else
1058 revised_command_line.Printf (" '%s'", next_word.c_str());
1059 }
1060 else
1061 revised_command_line.Printf (" %s", next_word.c_str());
Caroline Ticee0da7a52010-12-09 22:52:49 +00001062 done = true;
1063 }
1064 }
1065 else
1066 {
Caroline Tice649116c2011-05-11 16:07:06 +00001067 if (was_quoted)
1068 {
1069 if (quote_char == '"')
1070 revised_command_line.Printf (" \"%s\"", next_word.c_str());
1071 else
1072 revised_command_line.Printf (" '%s'", next_word.c_str());
1073 }
1074 else
1075 revised_command_line.Printf (" %s", next_word.c_str());
Caroline Ticee0da7a52010-12-09 22:52:49 +00001076 done = true;
1077 }
1078
1079 if (cmd_obj == NULL)
1080 {
1081 result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
1082 result.SetStatus (eReturnStatusFailed);
1083 return false;
1084 }
1085
1086 next_word.erase ();
1087 if (command_string.length() == 0)
1088 done = true;
1089
Chris Lattner24943d22010-06-08 16:52:24 +00001090 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001091
1092 if (command_string.size() > 0)
1093 revised_command_line.Printf (" %s", command_string.c_str());
1094
1095 // End of Phase 1.
1096 // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
1097 // specified was valid; revised_command_line contains the complete command line (including command name(s)),
1098 // fully translated with all substitutions & translations taken care of (still in raw text format); and
1099 // wants_raw_input specifies whether the Execute method expects raw input or not.
1100
1101
1102 if (log)
1103 {
1104 log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
1105 log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
1106 log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
1107 }
1108
1109 // Phase 2.
1110 // Take care of things like setting up the history command & calling the appropriate Execute method on the
1111 // CommandObject, with the appropriate arguments.
1112
1113 if (cmd_obj != NULL)
1114 {
1115 if (add_to_history)
1116 {
1117 Args command_args (revised_command_line.GetData());
1118 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
1119 if (repeat_command != NULL)
1120 m_repeat_command.assign(repeat_command);
1121 else
1122 m_repeat_command.assign(command_line);
1123
1124 m_command_history.push_back (command_line);
1125 }
1126
1127 command_string = revised_command_line.GetData();
1128 std::string command_name (cmd_obj->GetCommandName());
Caroline Ticeea6e3df2010-12-11 08:16:56 +00001129 std::string remainder;
1130 if (actual_cmd_name_len < command_string.length())
1131 remainder = command_string.substr (actual_cmd_name_len); // Note: 'actual_cmd_name_len' may be considerably shorter
1132 // than cmd_obj->GetCommandName(), because name completion
1133 // allows users to enter short versions of the names,
1134 // e.g. 'br s' for 'breakpoint set'.
Caroline Ticee0da7a52010-12-09 22:52:49 +00001135
1136 // Remove any initial spaces
1137 std::string white_space (" \t\v");
1138 size_t pos = remainder.find_first_not_of (white_space);
1139 if (pos != 0 && pos != std::string::npos)
Greg Clayton91c9dcf2011-04-22 20:58:45 +00001140 remainder.erase(0, pos);
Caroline Ticee0da7a52010-12-09 22:52:49 +00001141
1142 if (log)
1143 log->Printf ("HandleCommand, command line after removing command name(s): '%s'\n", remainder.c_str());
1144
1145
1146 if (wants_raw_input)
1147 cmd_obj->ExecuteRawCommandString (remainder.c_str(), result);
1148 else
1149 {
1150 Args cmd_args (remainder.c_str());
1151 cmd_obj->ExecuteWithOptions (cmd_args, result);
1152 }
1153 }
1154 else
1155 {
1156 // We didn't find the first command object, so complete the first argument.
1157 Args command_args (revised_command_line.GetData());
1158 StringList matches;
1159 int num_matches;
1160 int cursor_index = 0;
1161 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
1162 bool word_complete;
1163 num_matches = HandleCompletionMatches (command_args,
1164 cursor_index,
1165 cursor_char_position,
1166 0,
1167 -1,
1168 word_complete,
1169 matches);
1170
1171 if (num_matches > 0)
1172 {
1173 std::string error_msg;
1174 error_msg.assign ("ambiguous command '");
1175 error_msg.append(command_args.GetArgumentAtIndex(0));
1176 error_msg.append ("'.");
1177
1178 error_msg.append (" Possible completions:");
1179 for (int i = 0; i < num_matches; i++)
1180 {
1181 error_msg.append ("\n\t");
1182 error_msg.append (matches.GetStringAtIndex (i));
1183 }
1184 error_msg.append ("\n");
1185 result.AppendRawError (error_msg.c_str(), error_msg.size());
1186 }
1187 else
1188 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
1189
1190 result.SetStatus (eReturnStatusFailed);
1191 }
1192
Chris Lattner24943d22010-06-08 16:52:24 +00001193 return result.Succeeded();
1194}
1195
1196int
1197CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
1198 int &cursor_index,
1199 int &cursor_char_position,
1200 int match_start_point,
1201 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +00001202 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +00001203 StringList &matches)
1204{
1205 int num_command_matches = 0;
Chris Lattner24943d22010-06-08 16:52:24 +00001206 bool look_for_subcommand = false;
Jim Ingham802f8b02010-06-30 05:02:46 +00001207
1208 // For any of the command completions a unique match will be a complete word.
1209 word_complete = true;
Chris Lattner24943d22010-06-08 16:52:24 +00001210
1211 if (cursor_index == -1)
1212 {
1213 // We got nothing on the command line, so return the list of commands
Jim Inghamd40f8a62010-07-06 22:46:59 +00001214 bool include_aliases = true;
Chris Lattner24943d22010-06-08 16:52:24 +00001215 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
1216 }
1217 else if (cursor_index == 0)
1218 {
1219 // The cursor is in the first argument, so just do a lookup in the dictionary.
Jim Inghamd40f8a62010-07-06 22:46:59 +00001220 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
Chris Lattner24943d22010-06-08 16:52:24 +00001221 num_command_matches = matches.GetSize();
1222
1223 if (num_command_matches == 1
1224 && cmd_obj && cmd_obj->IsMultiwordObject()
1225 && matches.GetStringAtIndex(0) != NULL
1226 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
1227 {
1228 look_for_subcommand = true;
1229 num_command_matches = 0;
1230 matches.DeleteStringAtIndex(0);
1231 parsed_line.AppendArgument ("");
1232 cursor_index++;
1233 cursor_char_position = 0;
1234 }
1235 }
1236
1237 if (cursor_index > 0 || look_for_subcommand)
1238 {
1239 // We are completing further on into a commands arguments, so find the command and tell it
1240 // to complete the command.
1241 // First see if there is a matching initial command:
Jim Inghamd40f8a62010-07-06 22:46:59 +00001242 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
Chris Lattner24943d22010-06-08 16:52:24 +00001243 if (command_object == NULL)
1244 {
1245 return 0;
1246 }
1247 else
1248 {
1249 parsed_line.Shift();
1250 cursor_index--;
Greg Clayton238c0a12010-09-18 01:14:36 +00001251 num_command_matches = command_object->HandleCompletion (parsed_line,
Greg Clayton63094e02010-06-23 01:19:29 +00001252 cursor_index,
1253 cursor_char_position,
1254 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +00001255 max_return_elements,
1256 word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +00001257 matches);
1258 }
1259 }
1260
1261 return num_command_matches;
1262
1263}
1264
1265int
1266CommandInterpreter::HandleCompletion (const char *current_line,
1267 const char *cursor,
1268 const char *last_char,
1269 int match_start_point,
1270 int max_return_elements,
1271 StringList &matches)
1272{
1273 // We parse the argument up to the cursor, so the last argument in parsed_line is
1274 // the one containing the cursor, and the cursor is after the last character.
1275
1276 Args parsed_line(current_line, last_char - current_line);
1277 Args partial_parsed_line(current_line, cursor - current_line);
1278
1279 int num_args = partial_parsed_line.GetArgumentCount();
1280 int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
1281 int cursor_char_position;
1282
1283 if (cursor_index == -1)
1284 cursor_char_position = 0;
1285 else
1286 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
Jim Inghamcf037652010-12-14 19:56:01 +00001287
1288 if (cursor > current_line && cursor[-1] == ' ')
1289 {
1290 // We are just after a space. If we are in an argument, then we will continue
1291 // parsing, but if we are between arguments, then we have to complete whatever the next
1292 // element would be.
1293 // We can distinguish the two cases because if we are in an argument (e.g. because the space is
1294 // protected by a quote) then the space will also be in the parsed argument...
1295
1296 const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
1297 if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
1298 {
1299 parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '"');
1300 cursor_index++;
1301 cursor_char_position = 0;
1302 }
1303 }
Chris Lattner24943d22010-06-08 16:52:24 +00001304
1305 int num_command_matches;
1306
1307 matches.Clear();
1308
1309 // Only max_return_elements == -1 is supported at present:
1310 assert (max_return_elements == -1);
Jim Ingham802f8b02010-06-30 05:02:46 +00001311 bool word_complete;
Greg Clayton63094e02010-06-23 01:19:29 +00001312 num_command_matches = HandleCompletionMatches (parsed_line,
1313 cursor_index,
1314 cursor_char_position,
1315 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +00001316 max_return_elements,
1317 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +00001318 matches);
Chris Lattner24943d22010-06-08 16:52:24 +00001319
1320 if (num_command_matches <= 0)
1321 return num_command_matches;
1322
1323 if (num_args == 0)
1324 {
1325 // If we got an empty string, insert nothing.
1326 matches.InsertStringAtIndex(0, "");
1327 }
1328 else
1329 {
1330 // Now figure out if there is a common substring, and if so put that in element 0, otherwise
1331 // put an empty string in element 0.
1332 std::string command_partial_str;
1333 if (cursor_index >= 0)
Jim Inghame3663e82010-10-22 18:47:16 +00001334 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
1335 parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
Chris Lattner24943d22010-06-08 16:52:24 +00001336
1337 std::string common_prefix;
1338 matches.LongestCommonPrefix (common_prefix);
1339 int partial_name_len = command_partial_str.size();
1340
1341 // If we matched a unique single command, add a space...
Jim Ingham802f8b02010-06-30 05:02:46 +00001342 // Only do this if the completer told us this was a complete word, however...
1343 if (num_command_matches == 1 && word_complete)
Chris Lattner24943d22010-06-08 16:52:24 +00001344 {
1345 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
1346 if (quote_char != '\0')
1347 common_prefix.push_back(quote_char);
1348
1349 common_prefix.push_back(' ');
1350 }
1351 common_prefix.erase (0, partial_name_len);
1352 matches.InsertStringAtIndex(0, common_prefix.c_str());
1353 }
1354 return num_command_matches;
1355}
1356
Chris Lattner24943d22010-06-08 16:52:24 +00001357
1358CommandInterpreter::~CommandInterpreter ()
1359{
1360}
1361
1362const char *
1363CommandInterpreter::GetPrompt ()
1364{
Caroline Tice5bc8c972010-09-20 20:44:43 +00001365 return m_debugger.GetPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +00001366}
1367
1368void
1369CommandInterpreter::SetPrompt (const char *new_prompt)
1370{
Caroline Tice5bc8c972010-09-20 20:44:43 +00001371 m_debugger.SetPrompt (new_prompt);
Chris Lattner24943d22010-06-08 16:52:24 +00001372}
1373
Jim Ingham5e16ef52010-10-04 19:49:29 +00001374size_t
Greg Clayton58928562011-02-09 01:08:52 +00001375CommandInterpreter::GetConfirmationInputReaderCallback
1376(
1377 void *baton,
1378 InputReader &reader,
1379 lldb::InputReaderAction action,
1380 const char *bytes,
1381 size_t bytes_len
1382)
Jim Ingham5e16ef52010-10-04 19:49:29 +00001383{
Greg Clayton58928562011-02-09 01:08:52 +00001384 File &out_file = reader.GetDebugger().GetOutputFile();
Jim Ingham5e16ef52010-10-04 19:49:29 +00001385 bool *response_ptr = (bool *) baton;
1386
1387 switch (action)
1388 {
1389 case eInputReaderActivate:
Greg Clayton58928562011-02-09 01:08:52 +00001390 if (out_file.IsValid())
Jim Ingham5e16ef52010-10-04 19:49:29 +00001391 {
1392 if (reader.GetPrompt())
Caroline Tice22a60092011-02-02 01:17:56 +00001393 {
Greg Clayton58928562011-02-09 01:08:52 +00001394 out_file.Printf ("%s", reader.GetPrompt());
1395 out_file.Flush ();
Caroline Tice22a60092011-02-02 01:17:56 +00001396 }
Jim Ingham5e16ef52010-10-04 19:49:29 +00001397 }
1398 break;
1399
1400 case eInputReaderDeactivate:
1401 break;
1402
1403 case eInputReaderReactivate:
Greg Clayton58928562011-02-09 01:08:52 +00001404 if (out_file.IsValid() && reader.GetPrompt())
Caroline Tice22a60092011-02-02 01:17:56 +00001405 {
Greg Clayton58928562011-02-09 01:08:52 +00001406 out_file.Printf ("%s", reader.GetPrompt());
1407 out_file.Flush ();
Caroline Tice22a60092011-02-02 01:17:56 +00001408 }
Jim Ingham5e16ef52010-10-04 19:49:29 +00001409 break;
Caroline Tice4a348082011-05-02 20:41:46 +00001410
1411 case eInputReaderAsynchronousOutputWritten:
1412 break;
1413
Jim Ingham5e16ef52010-10-04 19:49:29 +00001414 case eInputReaderGotToken:
1415 if (bytes_len == 0)
1416 {
1417 reader.SetIsDone(true);
1418 }
1419 else if (bytes[0] == 'y')
1420 {
1421 *response_ptr = true;
1422 reader.SetIsDone(true);
1423 }
1424 else if (bytes[0] == 'n')
1425 {
1426 *response_ptr = false;
1427 reader.SetIsDone(true);
1428 }
1429 else
1430 {
Greg Clayton58928562011-02-09 01:08:52 +00001431 if (out_file.IsValid() && !reader.IsDone() && reader.GetPrompt())
Jim Ingham5e16ef52010-10-04 19:49:29 +00001432 {
Greg Clayton58928562011-02-09 01:08:52 +00001433 out_file.Printf ("Please answer \"y\" or \"n\"\n%s", reader.GetPrompt());
1434 out_file.Flush ();
Jim Ingham5e16ef52010-10-04 19:49:29 +00001435 }
1436 }
1437 break;
1438
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001439 case eInputReaderInterrupt:
1440 case eInputReaderEndOfFile:
1441 *response_ptr = false; // Assume ^C or ^D means cancel the proposed action
1442 reader.SetIsDone (true);
1443 break;
1444
Jim Ingham5e16ef52010-10-04 19:49:29 +00001445 case eInputReaderDone:
1446 break;
1447 }
1448
1449 return bytes_len;
1450
1451}
1452
1453bool
1454CommandInterpreter::Confirm (const char *message, bool default_answer)
1455{
Jim Ingham93057472010-10-04 22:44:14 +00001456 // Check AutoConfirm first:
1457 if (m_debugger.GetAutoConfirm())
1458 return default_answer;
1459
Jim Ingham5e16ef52010-10-04 19:49:29 +00001460 InputReaderSP reader_sp (new InputReader(GetDebugger()));
1461 bool response = default_answer;
1462 if (reader_sp)
1463 {
1464 std::string prompt(message);
1465 prompt.append(": [");
1466 if (default_answer)
1467 prompt.append ("Y/n] ");
1468 else
1469 prompt.append ("y/N] ");
1470
1471 Error err (reader_sp->Initialize (CommandInterpreter::GetConfirmationInputReaderCallback,
1472 &response, // baton
1473 eInputReaderGranularityLine, // token size, to pass to callback function
1474 NULL, // end token
1475 prompt.c_str(), // prompt
1476 true)); // echo input
1477 if (err.Success())
1478 {
1479 GetDebugger().PushInputReader (reader_sp);
1480 }
1481 reader_sp->WaitOnReaderIsDone();
1482 }
1483 return response;
1484}
1485
1486
Chris Lattner24943d22010-06-08 16:52:24 +00001487void
1488CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
1489{
Jim Inghamd40f8a62010-07-06 22:46:59 +00001490 CommandObjectSP cmd_obj_sp = GetCommandSPExact (dest_cmd, true);
Chris Lattner24943d22010-06-08 16:52:24 +00001491
1492 if (cmd_obj_sp != NULL)
1493 {
1494 CommandObject *cmd_obj = cmd_obj_sp.get();
1495 if (cmd_obj->IsCrossRefObject ())
1496 cmd_obj->AddObject (object_type);
1497 }
1498}
1499
Chris Lattner24943d22010-06-08 16:52:24 +00001500OptionArgVectorSP
1501CommandInterpreter::GetAliasOptions (const char *alias_name)
1502{
1503 OptionArgMap::iterator pos;
1504 OptionArgVectorSP ret_val;
1505
1506 std::string alias (alias_name);
1507
1508 if (HasAliasOptions())
1509 {
1510 pos = m_alias_options.find (alias);
1511 if (pos != m_alias_options.end())
1512 ret_val = pos->second;
1513 }
1514
1515 return ret_val;
1516}
1517
1518void
1519CommandInterpreter::RemoveAliasOptions (const char *alias_name)
1520{
1521 OptionArgMap::iterator pos = m_alias_options.find(alias_name);
1522 if (pos != m_alias_options.end())
1523 {
1524 m_alias_options.erase (pos);
1525 }
1526}
1527
1528void
1529CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
1530{
1531 m_alias_options[alias_name] = option_arg_vector_sp;
1532}
1533
1534bool
1535CommandInterpreter::HasCommands ()
1536{
1537 return (!m_command_dict.empty());
1538}
1539
1540bool
1541CommandInterpreter::HasAliases ()
1542{
1543 return (!m_alias_dict.empty());
1544}
1545
1546bool
1547CommandInterpreter::HasUserCommands ()
1548{
1549 return (!m_user_dict.empty());
1550}
1551
1552bool
1553CommandInterpreter::HasAliasOptions ()
1554{
1555 return (!m_alias_options.empty());
1556}
1557
Chris Lattner24943d22010-06-08 16:52:24 +00001558void
Caroline Ticebd5c63e2010-10-12 21:57:09 +00001559CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
1560 const char *alias_name,
1561 Args &cmd_args,
Caroline Tice44c841d2010-12-07 19:58:26 +00001562 std::string &raw_input_string,
Caroline Ticebd5c63e2010-10-12 21:57:09 +00001563 CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +00001564{
1565 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
Caroline Tice44c841d2010-12-07 19:58:26 +00001566
1567 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
Chris Lattner24943d22010-06-08 16:52:24 +00001568
Caroline Tice44c841d2010-12-07 19:58:26 +00001569 // Make sure that the alias name is the 0th element in cmd_args
1570 std::string alias_name_str = alias_name;
1571 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
1572 cmd_args.Unshift (alias_name);
1573
1574 Args new_args (alias_cmd_obj->GetCommandName());
1575 if (new_args.GetArgumentCount() == 2)
1576 new_args.Shift();
1577
Chris Lattner24943d22010-06-08 16:52:24 +00001578 if (option_arg_vector_sp.get())
1579 {
Caroline Tice44c841d2010-12-07 19:58:26 +00001580 if (wants_raw_input)
1581 {
1582 // We have a command that both has command options and takes raw input. Make *sure* it has a
1583 // " -- " in the right place in the raw_input_string.
1584 size_t pos = raw_input_string.find(" -- ");
1585 if (pos == std::string::npos)
1586 {
1587 // None found; assume it goes at the beginning of the raw input string
1588 raw_input_string.insert (0, " -- ");
1589 }
1590 }
Chris Lattner24943d22010-06-08 16:52:24 +00001591
1592 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1593 int old_size = cmd_args.GetArgumentCount();
Caroline Ticebd5c63e2010-10-12 21:57:09 +00001594 std::vector<bool> used (old_size + 1, false);
1595
1596 used[0] = true;
Chris Lattner24943d22010-06-08 16:52:24 +00001597
1598 for (int i = 0; i < option_arg_vector->size(); ++i)
1599 {
1600 OptionArgPair option_pair = (*option_arg_vector)[i];
Caroline Tice44c841d2010-12-07 19:58:26 +00001601 OptionArgValue value_pair = option_pair.second;
1602 int value_type = value_pair.first;
Chris Lattner24943d22010-06-08 16:52:24 +00001603 std::string option = option_pair.first;
Caroline Tice44c841d2010-12-07 19:58:26 +00001604 std::string value = value_pair.second;
Chris Lattner24943d22010-06-08 16:52:24 +00001605 if (option.compare ("<argument>") == 0)
Caroline Tice44c841d2010-12-07 19:58:26 +00001606 {
1607 if (!wants_raw_input
1608 || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
1609 new_args.AppendArgument (value.c_str());
1610 }
Chris Lattner24943d22010-06-08 16:52:24 +00001611 else
1612 {
Caroline Tice44c841d2010-12-07 19:58:26 +00001613 if (value_type != optional_argument)
1614 new_args.AppendArgument (option.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001615 if (value.compare ("<no-argument>") != 0)
1616 {
1617 int index = GetOptionArgumentPosition (value.c_str());
1618 if (index == 0)
Caroline Tice44c841d2010-12-07 19:58:26 +00001619 {
Chris Lattner24943d22010-06-08 16:52:24 +00001620 // value was NOT a positional argument; must be a real value
Caroline Tice44c841d2010-12-07 19:58:26 +00001621 if (value_type != optional_argument)
1622 new_args.AppendArgument (value.c_str());
1623 else
1624 {
1625 char buffer[255];
1626 ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
1627 new_args.AppendArgument (buffer);
1628 }
1629
1630 }
Chris Lattner24943d22010-06-08 16:52:24 +00001631 else if (index >= cmd_args.GetArgumentCount())
1632 {
1633 result.AppendErrorWithFormat
1634 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
1635 index);
1636 result.SetStatus (eReturnStatusFailed);
1637 return;
1638 }
1639 else
1640 {
Caroline Tice44c841d2010-12-07 19:58:26 +00001641 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
1642 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
1643 if (strpos != std::string::npos)
1644 {
1645 raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
1646 }
1647
1648 if (value_type != optional_argument)
1649 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
1650 else
1651 {
1652 char buffer[255];
1653 ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
1654 cmd_args.GetArgumentAtIndex (index));
1655 new_args.AppendArgument (buffer);
1656 }
Caroline Ticebd5c63e2010-10-12 21:57:09 +00001657 used[index] = true;
Chris Lattner24943d22010-06-08 16:52:24 +00001658 }
1659 }
1660 }
1661 }
1662
1663 for (int j = 0; j < cmd_args.GetArgumentCount(); ++j)
1664 {
Caroline Tice44c841d2010-12-07 19:58:26 +00001665 if (!used[j] && !wants_raw_input)
Chris Lattner24943d22010-06-08 16:52:24 +00001666 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
1667 }
1668
1669 cmd_args.Clear();
1670 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
1671 }
1672 else
1673 {
1674 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Caroline Tice44c841d2010-12-07 19:58:26 +00001675 // This alias was not created with any options; nothing further needs to be done, unless it is a command that
1676 // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
1677 // input string.
1678 if (wants_raw_input)
1679 {
1680 cmd_args.Clear();
1681 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
1682 }
Chris Lattner24943d22010-06-08 16:52:24 +00001683 return;
1684 }
1685
1686 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1687 return;
1688}
1689
1690
1691int
1692CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
1693{
1694 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
1695 // of zero.
1696
1697 char *cptr = (char *) in_string;
1698
1699 // Does it start with '%'
1700 if (cptr[0] == '%')
1701 {
1702 ++cptr;
1703
1704 // Is the rest of it entirely digits?
1705 if (isdigit (cptr[0]))
1706 {
1707 const char *start = cptr;
1708 while (isdigit (cptr[0]))
1709 ++cptr;
1710
1711 // We've gotten to the end of the digits; are we at the end of the string?
1712 if (cptr[0] == '\0')
1713 position = atoi (start);
1714 }
1715 }
1716
1717 return position;
1718}
1719
1720void
1721CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
1722{
Greg Clayton887aa282010-10-11 01:05:37 +00001723 // Don't parse any .lldbinit files if we were asked not to
1724 if (m_skip_lldbinit_files)
1725 return;
1726
Chris Lattner24943d22010-06-08 16:52:24 +00001727 const char *init_file_path = in_cwd ? "./.lldbinit" : "~/.lldbinit";
Greg Clayton537a7a82010-10-20 20:54:39 +00001728 FileSpec init_file (init_file_path, true);
Chris Lattner24943d22010-06-08 16:52:24 +00001729 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
1730 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
1731
1732 if (init_file.Exists())
1733 {
Jim Ingham949d5ac2011-02-18 00:54:25 +00001734 ExecutionContext *exe_ctx = NULL; // We don't have any context yet.
1735 bool stop_on_continue = true;
1736 bool stop_on_error = false;
1737 bool echo_commands = false;
1738 bool print_results = false;
1739
1740 HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, result);
Chris Lattner24943d22010-06-08 16:52:24 +00001741 }
1742 else
1743 {
1744 // nothing to be done if the file doesn't exist
1745 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1746 }
1747}
1748
Greg Claytonb72d0f02011-04-12 05:54:46 +00001749PlatformSP
1750CommandInterpreter::GetPlatform (bool prefer_target_platform)
1751{
1752 PlatformSP platform_sp;
1753 if (prefer_target_platform && m_exe_ctx.target)
1754 platform_sp = m_exe_ctx.target->GetPlatform();
1755
1756 if (!platform_sp)
1757 platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
1758 return platform_sp;
1759}
1760
Jim Ingham949d5ac2011-02-18 00:54:25 +00001761void
Jim Inghama4fede32011-03-11 01:51:49 +00001762CommandInterpreter::HandleCommands (const StringList &commands,
Jim Ingham949d5ac2011-02-18 00:54:25 +00001763 ExecutionContext *override_context,
1764 bool stop_on_continue,
1765 bool stop_on_error,
1766 bool echo_commands,
1767 bool print_results,
1768 CommandReturnObject &result)
1769{
1770 size_t num_lines = commands.GetSize();
Jim Ingham949d5ac2011-02-18 00:54:25 +00001771
1772 // If we are going to continue past a "continue" then we need to run the commands synchronously.
1773 // Make sure you reset this value anywhere you return from the function.
1774
1775 bool old_async_execution = m_debugger.GetAsyncExecution();
1776
1777 // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
1778 // cause series of commands that change the context, then do an operation that relies on that context to fail.
1779
1780 if (override_context != NULL)
Greg Claytonb72d0f02011-04-12 05:54:46 +00001781 UpdateExecutionContext (override_context);
Jim Ingham949d5ac2011-02-18 00:54:25 +00001782
1783 if (!stop_on_continue)
1784 {
1785 m_debugger.SetAsyncExecution (false);
1786 }
1787
1788 for (int idx = 0; idx < num_lines; idx++)
1789 {
1790 const char *cmd = commands.GetStringAtIndex(idx);
1791 if (cmd[0] == '\0')
1792 continue;
1793
Jim Ingham949d5ac2011-02-18 00:54:25 +00001794 if (echo_commands)
1795 {
1796 result.AppendMessageWithFormat ("%s %s\n",
1797 GetPrompt(),
1798 cmd);
1799 }
1800
Greg Claytonaa378b12011-02-20 02:15:07 +00001801 CommandReturnObject tmp_result;
Jim Ingham949d5ac2011-02-18 00:54:25 +00001802 bool success = HandleCommand(cmd, false, tmp_result, NULL);
1803
1804 if (print_results)
1805 {
1806 if (tmp_result.Succeeded())
Jim Ingham2e8cb8a2011-02-19 02:53:09 +00001807 result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
Jim Ingham949d5ac2011-02-18 00:54:25 +00001808 }
1809
1810 if (!success || !tmp_result.Succeeded())
1811 {
1812 if (stop_on_error)
1813 {
1814 result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' failed.\n",
1815 idx, cmd);
1816 result.SetStatus (eReturnStatusFailed);
1817 m_debugger.SetAsyncExecution (old_async_execution);
1818 return;
1819 }
1820 else if (print_results)
1821 {
1822 result.AppendMessageWithFormat ("Command #%d '%s' failed with error: %s.\n",
1823 idx + 1,
1824 cmd,
Jim Ingham2e8cb8a2011-02-19 02:53:09 +00001825 tmp_result.GetErrorData());
Jim Ingham949d5ac2011-02-18 00:54:25 +00001826 }
1827 }
1828
Caroline Tice4a348082011-05-02 20:41:46 +00001829 if (result.GetImmediateOutputStream())
1830 result.GetImmediateOutputStream()->Flush();
1831
1832 if (result.GetImmediateErrorStream())
1833 result.GetImmediateErrorStream()->Flush();
1834
Jim Ingham949d5ac2011-02-18 00:54:25 +00001835 // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
1836 // could be running (for instance in Breakpoint Commands.
1837 // So we check the return value to see if it is has running in it.
1838 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
1839 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
1840 {
1841 if (stop_on_continue)
1842 {
1843 // If we caused the target to proceed, and we're going to stop in that case, set the
1844 // status in our real result before returning. This is an error if the continue was not the
1845 // last command in the set of commands to be run.
1846 if (idx != num_lines - 1)
1847 result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' continued the target.\n",
1848 idx + 1, cmd);
1849 else
1850 result.AppendMessageWithFormat ("Command #%d '%s' continued the target.\n", idx + 1, cmd);
1851
1852 result.SetStatus(tmp_result.GetStatus());
1853 m_debugger.SetAsyncExecution (old_async_execution);
1854
1855 return;
1856 }
1857 }
1858
1859 }
1860
1861 result.SetStatus (eReturnStatusSuccessFinishResult);
1862 m_debugger.SetAsyncExecution (old_async_execution);
1863
1864 return;
1865}
1866
1867void
1868CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
1869 ExecutionContext *context,
1870 bool stop_on_continue,
1871 bool stop_on_error,
1872 bool echo_command,
1873 bool print_result,
1874 CommandReturnObject &result)
1875{
1876 if (cmd_file.Exists())
1877 {
1878 bool success;
1879 StringList commands;
1880 success = commands.ReadFileLines(cmd_file);
1881 if (!success)
1882 {
1883 result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString());
1884 result.SetStatus (eReturnStatusFailed);
1885 return;
1886 }
1887 HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, result);
1888 }
1889 else
1890 {
1891 result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
1892 cmd_file.GetFilename().AsCString());
1893 result.SetStatus (eReturnStatusFailed);
1894 return;
1895 }
1896}
1897
Chris Lattner24943d22010-06-08 16:52:24 +00001898ScriptInterpreter *
1899CommandInterpreter::GetScriptInterpreter ()
1900{
Caroline Tice0aa2e552011-01-14 00:29:16 +00001901 if (m_script_interpreter_ap.get() != NULL)
1902 return m_script_interpreter_ap.get();
Greg Clayton63094e02010-06-23 01:19:29 +00001903
Caroline Tice0aa2e552011-01-14 00:29:16 +00001904 lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
1905 switch (script_lang)
Chris Lattner24943d22010-06-08 16:52:24 +00001906 {
Caroline Tice0aa2e552011-01-14 00:29:16 +00001907 case eScriptLanguageNone:
1908 m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
1909 break;
1910 case eScriptLanguagePython:
1911 m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
1912 break;
1913 default:
1914 break;
1915 };
1916
1917 return m_script_interpreter_ap.get();
Chris Lattner24943d22010-06-08 16:52:24 +00001918}
1919
1920
1921
1922bool
1923CommandInterpreter::GetSynchronous ()
1924{
1925 return m_synchronous_execution;
1926}
1927
1928void
1929CommandInterpreter::SetSynchronous (bool value)
1930{
Johnny Chend7a4eb02010-10-14 01:22:03 +00001931 m_synchronous_execution = value;
Chris Lattner24943d22010-06-08 16:52:24 +00001932}
1933
1934void
1935CommandInterpreter::OutputFormattedHelpText (Stream &strm,
1936 const char *word_text,
1937 const char *separator,
1938 const char *help_text,
1939 uint32_t max_word_len)
1940{
Greg Clayton238c0a12010-09-18 01:14:36 +00001941 const uint32_t max_columns = m_debugger.GetTerminalWidth();
1942
Chris Lattner24943d22010-06-08 16:52:24 +00001943 int indent_size = max_word_len + strlen (separator) + 2;
1944
1945 strm.IndentMore (indent_size);
Greg Claytond284b662011-02-18 01:44:25 +00001946
1947 StreamString text_strm;
1948 text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
1949
1950 size_t len = text_strm.GetSize();
1951 const char *text = text_strm.GetData();
Chris Lattner24943d22010-06-08 16:52:24 +00001952 if (text[len - 1] == '\n')
Greg Claytond284b662011-02-18 01:44:25 +00001953 {
1954 text_strm.EOL();
1955 len = text_strm.GetSize();
1956 }
Chris Lattner24943d22010-06-08 16:52:24 +00001957
1958 if (len < max_columns)
1959 {
1960 // Output it as a single line.
1961 strm.Printf ("%s", text);
1962 }
1963 else
1964 {
1965 // We need to break it up into multiple lines.
1966 bool first_line = true;
1967 int text_width;
1968 int start = 0;
1969 int end = start;
1970 int final_end = strlen (text);
1971 int sub_len;
1972
1973 while (end < final_end)
1974 {
1975 if (first_line)
1976 text_width = max_columns - 1;
1977 else
1978 text_width = max_columns - indent_size - 1;
1979
1980 // Don't start the 'text' on a space, since we're already outputting the indentation.
1981 if (!first_line)
1982 {
1983 while ((start < final_end) && (text[start] == ' '))
1984 start++;
1985 }
1986
1987 end = start + text_width;
1988 if (end > final_end)
1989 end = final_end;
1990 else
1991 {
1992 // If we're not at the end of the text, make sure we break the line on white space.
1993 while (end > start
1994 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
1995 end--;
1996 }
1997
1998 sub_len = end - start;
1999 if (start != 0)
2000 strm.EOL();
2001 if (!first_line)
2002 strm.Indent();
2003 else
2004 first_line = false;
2005 assert (start <= final_end);
2006 assert (start + sub_len <= final_end);
2007 if (sub_len > 0)
2008 strm.Write (text + start, sub_len);
2009 start = end + 1;
2010 }
2011 }
2012 strm.EOL();
2013 strm.IndentLess(indent_size);
Chris Lattner24943d22010-06-08 16:52:24 +00002014}
2015
2016void
2017CommandInterpreter::AproposAllSubCommands (CommandObject *cmd_obj, const char *prefix, const char *search_word,
2018 StringList &commands_found, StringList &commands_help)
2019{
2020 CommandObject::CommandMap::const_iterator pos;
2021 CommandObject::CommandMap sub_cmd_dict = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict;
2022 CommandObject *sub_cmd_obj;
2023
2024 for (pos = sub_cmd_dict.begin(); pos != sub_cmd_dict.end(); ++pos)
2025 {
2026 const char * command_name = pos->first.c_str();
2027 sub_cmd_obj = pos->second.get();
2028 StreamString complete_command_name;
2029
2030 complete_command_name.Printf ("%s %s", prefix, command_name);
2031
Greg Clayton238c0a12010-09-18 01:14:36 +00002032 if (sub_cmd_obj->HelpTextContainsWord (search_word))
Chris Lattner24943d22010-06-08 16:52:24 +00002033 {
2034 commands_found.AppendString (complete_command_name.GetData());
2035 commands_help.AppendString (sub_cmd_obj->GetHelp());
2036 }
2037
2038 if (sub_cmd_obj->IsMultiwordObject())
2039 AproposAllSubCommands (sub_cmd_obj, complete_command_name.GetData(), search_word, commands_found,
2040 commands_help);
2041 }
2042
2043}
2044
2045void
2046CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
2047 StringList &commands_help)
2048{
2049 CommandObject::CommandMap::const_iterator pos;
2050
2051 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
2052 {
2053 const char *command_name = pos->first.c_str();
2054 CommandObject *cmd_obj = pos->second.get();
2055
Greg Clayton238c0a12010-09-18 01:14:36 +00002056 if (cmd_obj->HelpTextContainsWord (search_word))
Chris Lattner24943d22010-06-08 16:52:24 +00002057 {
2058 commands_found.AppendString (command_name);
2059 commands_help.AppendString (cmd_obj->GetHelp());
2060 }
2061
2062 if (cmd_obj->IsMultiwordObject())
2063 AproposAllSubCommands (cmd_obj, command_name, search_word, commands_found, commands_help);
2064
2065 }
2066}
Greg Claytonb72d0f02011-04-12 05:54:46 +00002067
2068
2069void
2070CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
2071{
2072 m_exe_ctx.Clear();
2073
2074 if (override_context != NULL)
2075 {
2076 m_exe_ctx.target = override_context->target;
2077 m_exe_ctx.process = override_context->process;
2078 m_exe_ctx.thread = override_context->thread;
2079 m_exe_ctx.frame = override_context->frame;
2080 }
2081 else
2082 {
2083 TargetSP target_sp (m_debugger.GetSelectedTarget());
2084 if (target_sp)
2085 {
2086 m_exe_ctx.target = target_sp.get();
2087 m_exe_ctx.process = target_sp->GetProcessSP().get();
2088 if (m_exe_ctx.process && m_exe_ctx.process->IsAlive() && !m_exe_ctx.process->IsRunning())
2089 {
2090 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetSelectedThread().get();
2091 if (m_exe_ctx.thread == NULL)
2092 {
2093 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
2094 // If we didn't have a selected thread, select one here.
2095 if (m_exe_ctx.thread != NULL)
2096 m_exe_ctx.process->GetThreadList().SetSelectedThreadByID(m_exe_ctx.thread->GetID());
2097 }
2098 if (m_exe_ctx.thread)
2099 {
2100 m_exe_ctx.frame = m_exe_ctx.thread->GetSelectedFrame().get();
2101 if (m_exe_ctx.frame == NULL)
2102 {
2103 m_exe_ctx.frame = m_exe_ctx.thread->GetStackFrameAtIndex (0).get();
2104 // If we didn't have a selected frame select one here.
2105 if (m_exe_ctx.frame != NULL)
2106 m_exe_ctx.thread->SetSelectedFrame(m_exe_ctx.frame);
2107 }
2108 }
2109 }
2110 }
2111 }
2112}
2113