blob: 979e21a5492b3b354b9b07f94d9065e1fe149706 [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"
Johnny Chen01acfa72011-09-22 18:04:58 +000040#include "../Commands/CommandObjectWatchpoint.h"
Chris Lattner24943d22010-06-08 16:52:24 +000041
Jim Ingham84cdc152010-06-15 19:49:27 +000042#include "lldb/Interpreter/Args.h"
Caroline Tice5ddbe212011-05-06 21:37:15 +000043#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000044#include "lldb/Core/Debugger.h"
Jim Ingham5e16ef52010-10-04 19:49:29 +000045#include "lldb/Core/InputReader.h"
Chris Lattner24943d22010-06-08 16:52:24 +000046#include "lldb/Core/Stream.h"
47#include "lldb/Core/Timer.h"
Greg Claytoncd548032011-02-01 01:31:41 +000048#include "lldb/Host/Host.h"
Chris Lattner24943d22010-06-08 16:52:24 +000049#include "lldb/Target/Process.h"
50#include "lldb/Target/Thread.h"
51#include "lldb/Target/TargetList.h"
Greg Claytone98ac252010-11-10 04:57:04 +000052#include "lldb/Utility/CleanUp.h"
Chris Lattner24943d22010-06-08 16:52:24 +000053
54#include "lldb/Interpreter/CommandReturnObject.h"
55#include "lldb/Interpreter/CommandInterpreter.h"
Caroline Tice0aa2e552011-01-14 00:29:16 +000056#include "lldb/Interpreter/ScriptInterpreterNone.h"
57#include "lldb/Interpreter/ScriptInterpreterPython.h"
Chris Lattner24943d22010-06-08 16:52:24 +000058
59using namespace lldb;
60using namespace lldb_private;
61
Jim Ingham5a15e692012-02-16 06:50:00 +000062ConstString &
63CommandInterpreter::GetStaticBroadcasterClass ()
64{
65 static ConstString class_name ("lldb.commandInterpreter");
66 return class_name;
67}
68
Chris Lattner24943d22010-06-08 16:52:24 +000069CommandInterpreter::CommandInterpreter
70(
Greg Clayton63094e02010-06-23 01:19:29 +000071 Debugger &debugger,
Chris Lattner24943d22010-06-08 16:52:24 +000072 ScriptLanguage script_language,
Greg Clayton63094e02010-06-23 01:19:29 +000073 bool synchronous_execution
Chris Lattner24943d22010-06-08 16:52:24 +000074) :
Jim Ingham5a15e692012-02-16 06:50:00 +000075 Broadcaster (&debugger, "lldb.command-interpreter"),
Greg Clayton63094e02010-06-23 01:19:29 +000076 m_debugger (debugger),
Greg Clayton887aa282010-10-11 01:05:37 +000077 m_synchronous_execution (synchronous_execution),
Caroline Tice0aa2e552011-01-14 00:29:16 +000078 m_skip_lldbinit_files (false),
Jim Ingham574c3d62011-08-12 23:34:31 +000079 m_skip_app_init_files (false),
Jim Ingham949d5ac2011-02-18 00:54:25 +000080 m_script_interpreter_ap (),
Caroline Tice892fadd2011-06-16 16:27:19 +000081 m_comment_char ('#'),
Jim Ingham6247dbe2011-07-12 03:12:18 +000082 m_repeat_char ('!'),
Johnny Chen3908bb12012-08-09 22:06:10 +000083 m_batch_command_mode (false),
Enrico Granata01bc2d42012-05-31 01:09:06 +000084 m_truncation_warning(eNoTruncation),
85 m_command_source_depth (0)
Chris Lattner24943d22010-06-08 16:52:24 +000086{
Caroline Tice6e4c5ce2010-09-04 00:03:46 +000087 const char *dbg_name = debugger.GetInstanceName().AsCString();
88 std::string lang_name = ScriptInterpreter::LanguageToString (script_language);
89 StreamString var_name;
90 var_name.Printf ("[%s].script-lang", dbg_name);
Caroline Tice1d2aefd2010-09-09 06:25:08 +000091 debugger.GetSettingsController()->SetVariable (var_name.GetData(), lang_name.c_str(),
Greg Claytonb3448432011-03-24 21:19:54 +000092 eVarSetOperationAssign, false,
Greg Clayton49ce6822010-10-31 03:01:06 +000093 m_debugger.GetInstanceName().AsCString());
94 SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
95 SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
96 SetEventName (eBroadcastBitQuitCommandReceived, "quit");
Jim Ingham5a15e692012-02-16 06:50:00 +000097
98 CheckInWithManager ();
Chris Lattner24943d22010-06-08 16:52:24 +000099}
100
101void
102CommandInterpreter::Initialize ()
103{
104 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
105
106 CommandReturnObject result;
107
108 LoadCommandDictionary ();
109
Chris Lattner24943d22010-06-08 16:52:24 +0000110 // Set up some initial aliases.
Caroline Tice5ddbe212011-05-06 21:37:15 +0000111 CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
112 if (cmd_obj_sp)
113 {
114 AddAlias ("q", cmd_obj_sp);
115 AddAlias ("exit", cmd_obj_sp);
116 }
Sean Callananfc58af22012-05-04 23:15:02 +0000117
118 cmd_obj_sp = GetCommandSPExact ("process attach", false);
119 if (cmd_obj_sp)
120 {
121 AddAlias ("attach", cmd_obj_sp);
122 }
Caroline Tice5ddbe212011-05-06 21:37:15 +0000123
124 cmd_obj_sp = GetCommandSPExact ("process continue", false);
125 if (cmd_obj_sp)
126 {
127 AddAlias ("c", cmd_obj_sp);
128 AddAlias ("continue", cmd_obj_sp);
129 }
130
131 cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
132 if (cmd_obj_sp)
133 AddAlias ("b", cmd_obj_sp);
134
135 cmd_obj_sp = GetCommandSPExact ("thread backtrace", false);
136 if (cmd_obj_sp)
137 AddAlias ("bt", cmd_obj_sp);
138
139 cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
140 if (cmd_obj_sp)
Jason Molenda47eb00e2011-10-22 00:47:41 +0000141 {
142 AddAlias ("stepi", cmd_obj_sp);
Caroline Tice5ddbe212011-05-06 21:37:15 +0000143 AddAlias ("si", cmd_obj_sp);
Jason Molenda47eb00e2011-10-22 00:47:41 +0000144 }
145
146 cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false);
147 if (cmd_obj_sp)
148 {
149 AddAlias ("nexti", cmd_obj_sp);
150 AddAlias ("ni", cmd_obj_sp);
151 }
Caroline Tice5ddbe212011-05-06 21:37:15 +0000152
153 cmd_obj_sp = GetCommandSPExact ("thread step-in", false);
154 if (cmd_obj_sp)
155 {
156 AddAlias ("s", cmd_obj_sp);
157 AddAlias ("step", cmd_obj_sp);
158 }
159
160 cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
161 if (cmd_obj_sp)
162 {
163 AddAlias ("n", cmd_obj_sp);
164 AddAlias ("next", cmd_obj_sp);
165 }
166
167 cmd_obj_sp = GetCommandSPExact ("thread step-out", false);
168 if (cmd_obj_sp)
169 {
Caroline Tice5ddbe212011-05-06 21:37:15 +0000170 AddAlias ("finish", cmd_obj_sp);
171 }
172
Jim Ingham59355252011-12-02 01:12:59 +0000173 cmd_obj_sp = GetCommandSPExact ("frame select", false);
174 if (cmd_obj_sp)
175 {
176 AddAlias ("f", cmd_obj_sp);
177 }
178
Caroline Tice5ddbe212011-05-06 21:37:15 +0000179 cmd_obj_sp = GetCommandSPExact ("source list", false);
180 if (cmd_obj_sp)
181 {
182 AddAlias ("l", cmd_obj_sp);
183 AddAlias ("list", cmd_obj_sp);
184 }
185
186 cmd_obj_sp = GetCommandSPExact ("memory read", false);
187 if (cmd_obj_sp)
188 AddAlias ("x", cmd_obj_sp);
189
190 cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
191 if (cmd_obj_sp)
192 AddAlias ("up", cmd_obj_sp);
193
194 cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
195 if (cmd_obj_sp)
196 AddAlias ("down", cmd_obj_sp);
197
Jason Molenda3f2ec9b2011-10-25 02:11:20 +0000198 cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
Jason Molenda730cae02011-10-22 01:30:52 +0000199 if (cmd_obj_sp)
200 AddAlias ("display", cmd_obj_sp);
Jim Ingham9d1acc12011-10-24 18:37:00 +0000201
202 cmd_obj_sp = GetCommandSPExact ("disassemble", false);
203 if (cmd_obj_sp)
204 AddAlias ("dis", cmd_obj_sp);
205
206 cmd_obj_sp = GetCommandSPExact ("disassemble", false);
207 if (cmd_obj_sp)
208 AddAlias ("di", cmd_obj_sp);
209
210
Jason Molenda730cae02011-10-22 01:30:52 +0000211
Jason Molenda3f2ec9b2011-10-25 02:11:20 +0000212 cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
Jason Molenda730cae02011-10-22 01:30:52 +0000213 if (cmd_obj_sp)
214 AddAlias ("undisplay", cmd_obj_sp);
215
Caroline Tice5ddbe212011-05-06 21:37:15 +0000216 cmd_obj_sp = GetCommandSPExact ("target create", false);
217 if (cmd_obj_sp)
218 AddAlias ("file", cmd_obj_sp);
219
220 cmd_obj_sp = GetCommandSPExact ("target modules", false);
221 if (cmd_obj_sp)
222 AddAlias ("image", cmd_obj_sp);
223
224
225 OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
Jim Inghame56493f2011-03-22 02:29:32 +0000226
Caroline Tice5ddbe212011-05-06 21:37:15 +0000227 cmd_obj_sp = GetCommandSPExact ("expression", false);
228 if (cmd_obj_sp)
229 {
230 AddAlias ("expr", cmd_obj_sp);
231
232 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
233 AddAlias ("p", cmd_obj_sp);
234 AddAlias ("print", cmd_obj_sp);
Sean Callanan59959eb2012-08-08 01:30:34 +0000235 AddAlias ("call", cmd_obj_sp);
Caroline Tice5ddbe212011-05-06 21:37:15 +0000236 AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp);
237 AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp);
Sean Callanan59959eb2012-08-08 01:30:34 +0000238 AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp);
Caroline Tice5ddbe212011-05-06 21:37:15 +0000239
240 alias_arguments_vector_sp.reset (new OptionArgVector);
241 ProcessAliasOptionsArgs (cmd_obj_sp, "-o --", alias_arguments_vector_sp);
242 AddAlias ("po", cmd_obj_sp);
243 AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
244 }
245
Sean Callananee301fa2012-06-01 23:29:32 +0000246 cmd_obj_sp = GetCommandSPExact ("process kill", false);
247 if (cmd_obj_sp)
248 AddAlias ("kill", cmd_obj_sp);
249
Caroline Tice5ddbe212011-05-06 21:37:15 +0000250 cmd_obj_sp = GetCommandSPExact ("process launch", false);
251 if (cmd_obj_sp)
252 {
253 alias_arguments_vector_sp.reset (new OptionArgVector);
Jason Molenda36eb7c02012-07-06 02:46:23 +0000254#if defined (__arm__)
255 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
256#else
Greg Clayton86c50d72012-05-18 00:04:38 +0000257 ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=/bin/bash --", alias_arguments_vector_sp);
Jason Molenda36eb7c02012-07-06 02:46:23 +0000258#endif
Caroline Tice5ddbe212011-05-06 21:37:15 +0000259 AddAlias ("r", cmd_obj_sp);
260 AddAlias ("run", cmd_obj_sp);
261 AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp);
262 AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp);
263 }
Greg Claytonc84623f2012-03-29 21:47:51 +0000264
265 cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
266 if (cmd_obj_sp)
267 {
268 AddAlias ("add-dsym", cmd_obj_sp);
269 }
Sean Callanan7b71b172012-05-21 18:25:19 +0000270
271 cmd_obj_sp = GetCommandSPExact ("breakpoint set", false);
272 if (cmd_obj_sp)
273 {
274 alias_arguments_vector_sp.reset (new OptionArgVector);
275 ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp);
276 AddAlias ("rb", cmd_obj_sp);
277 AddOrReplaceAliasOptions("rb", alias_arguments_vector_sp);
278 }
Chris Lattner24943d22010-06-08 16:52:24 +0000279}
280
Chris Lattner24943d22010-06-08 16:52:24 +0000281const char *
282CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
283{
284 // This function has not yet been implemented.
285
286 // Look for any embedded script command
287 // If found,
288 // get interpreter object from the command dictionary,
289 // call execute_one_command on it,
290 // get the results as a string,
291 // substitute that string for current stuff.
292
293 return arg;
294}
295
296
297void
298CommandInterpreter::LoadCommandDictionary ()
299{
300 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
301
302 // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
303 //
304 // Command objects that are used as cross reference objects (i.e. they inherit from CommandObjectCrossref)
305 // *MUST* be created and put into the command dictionary *BEFORE* any multi-word commands (which may use
306 // the cross-referencing stuff) are created!!!
307 //
308 // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
309
310
311 // Command objects that inherit from CommandObjectCrossref must be created before other command objects
312 // are created. This is so that when another command is created that needs to go into a crossref object,
313 // the crossref object exists and is ready to take the cross reference. Put the cross referencing command
314 // objects into the CommandDictionary now, so they are ready for use when the other commands get created.
315
Chris Lattner24943d22010-06-08 16:52:24 +0000316 // Non-CommandObjectCrossref commands can now be created.
317
Caroline Tice5bc8c972010-09-20 20:44:43 +0000318 lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000319
Greg Clayton238c0a12010-09-18 01:14:36 +0000320 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000321 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
Greg Clayton238c0a12010-09-18 01:14:36 +0000322 //m_command_dict["call"] = CommandObjectSP (new CommandObjectCall (*this));
Johnny Chen9e4c3d72011-04-21 00:39:18 +0000323 m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
Greg Clayton238c0a12010-09-18 01:14:36 +0000324 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
325 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
Greg Claytonabe0fed2011-04-18 08:33:37 +0000326// m_command_dict["file"] = CommandObjectSP (new CommandObjectFile (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000327 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
Greg Clayton238c0a12010-09-18 01:14:36 +0000328 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this));
Greg Claytone1f50b92011-05-03 22:09:39 +0000329 /// m_command_dict["image"] = CommandObjectSP (new CommandObjectImage (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000330 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this));
331 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this));
Greg Claytonb1888f22011-03-19 01:12:21 +0000332 m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000333 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
Greg Clayton238c0a12010-09-18 01:14:36 +0000334 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000335 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this));
Greg Clayton238c0a12010-09-18 01:14:36 +0000336 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language));
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000337 m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
Jim Ingham767af882010-07-07 03:36:20 +0000338 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this));
Greg Clayton63094e02010-06-23 01:19:29 +0000339 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
340 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this));
Enrico Granata6b1596d2011-08-16 23:24:13 +0000341 m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this));
Johnny Chen902e0182010-12-23 20:21:44 +0000342 m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this));
Johnny Chen01acfa72011-09-22 18:04:58 +0000343 m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
Chris Lattner24943d22010-06-08 16:52:24 +0000344
345 std::auto_ptr<CommandObjectRegexCommand>
Greg Clayton238c0a12010-09-18 01:14:36 +0000346 break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Claytonb72d0f02011-04-12 05:54:46 +0000347 "_regexp-break",
Caroline Ticec1ad82e2010-09-07 22:38:08 +0000348 "Set a breakpoint using a regular expression to specify the location.",
Greg Claytonb72d0f02011-04-12 05:54:46 +0000349 "_regexp-break [<filename>:<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 2));
Chris Lattner24943d22010-06-08 16:52:24 +0000350 if (break_regex_cmd_ap.get())
351 {
352 if (break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2") &&
353 break_regex_cmd_ap->AddRegexCommand("^(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1") &&
354 break_regex_cmd_ap->AddRegexCommand("^[\"']?([-+]\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'") &&
Greg Claytonb72d0f02011-04-12 05:54:46 +0000355 break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full") &&
Chris Lattner24943d22010-06-08 16:52:24 +0000356 break_regex_cmd_ap->AddRegexCommand("^(-.*)$", "breakpoint set %1") &&
Greg Claytonb01000f2011-01-17 03:46:26 +0000357 break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'") &&
Chris Lattner24943d22010-06-08 16:52:24 +0000358 break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"))
359 {
360 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
361 m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
362 }
363 }
Jim Inghame56493f2011-03-22 02:29:32 +0000364
365 std::auto_ptr<CommandObjectRegexCommand>
366 down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Claytonb72d0f02011-04-12 05:54:46 +0000367 "_regexp-down",
368 "Go down \"n\" frames in the stack (1 frame by default).",
369 "_regexp-down [n]", 2));
Jim Inghame56493f2011-03-22 02:29:32 +0000370 if (down_regex_cmd_ap.get())
371 {
372 if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
373 down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1"))
374 {
375 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
376 m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
377 }
378 }
379
380 std::auto_ptr<CommandObjectRegexCommand>
381 up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Claytonb72d0f02011-04-12 05:54:46 +0000382 "_regexp-up",
383 "Go up \"n\" frames in the stack (1 frame by default).",
384 "_regexp-up [n]", 2));
Jim Inghame56493f2011-03-22 02:29:32 +0000385 if (up_regex_cmd_ap.get())
386 {
387 if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
388 up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1"))
389 {
390 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
391 m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp;
392 }
393 }
Jason Molenda730cae02011-10-22 01:30:52 +0000394
395 std::auto_ptr<CommandObjectRegexCommand>
396 display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Jason Molenda3f2ec9b2011-10-25 02:11:20 +0000397 "_regexp-display",
Jason Molenda730cae02011-10-22 01:30:52 +0000398 "Add an expression evaluation stop-hook.",
Jason Molenda3f2ec9b2011-10-25 02:11:20 +0000399 "_regexp-display expression", 2));
Jason Molenda730cae02011-10-22 01:30:52 +0000400 if (display_regex_cmd_ap.get())
401 {
402 if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
403 {
404 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release());
405 m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp;
406 }
407 }
408
409 std::auto_ptr<CommandObjectRegexCommand>
410 undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Jason Molenda3f2ec9b2011-10-25 02:11:20 +0000411 "_regexp-undisplay",
Jason Molenda730cae02011-10-22 01:30:52 +0000412 "Remove an expression evaluation stop-hook.",
Jason Molenda3f2ec9b2011-10-25 02:11:20 +0000413 "_regexp-undisplay stop-hook-number", 2));
Jason Molenda730cae02011-10-22 01:30:52 +0000414 if (undisplay_regex_cmd_ap.get())
415 {
416 if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
417 {
418 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release());
419 m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp;
420 }
421 }
422
Chris Lattner24943d22010-06-08 16:52:24 +0000423}
424
425int
426CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
427 StringList &matches)
428{
429 CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
430
431 if (include_aliases)
432 {
433 CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
434 }
435
436 return matches.GetSize();
437}
438
439CommandObjectSP
440CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
441{
442 CommandObject::CommandMap::iterator pos;
443 CommandObjectSP ret_val;
444
445 std::string cmd(cmd_cstr);
446
447 if (HasCommands())
448 {
449 pos = m_command_dict.find(cmd);
450 if (pos != m_command_dict.end())
451 ret_val = pos->second;
452 }
453
454 if (include_aliases && HasAliases())
455 {
456 pos = m_alias_dict.find(cmd);
457 if (pos != m_alias_dict.end())
458 ret_val = pos->second;
459 }
460
461 if (HasUserCommands())
462 {
463 pos = m_user_dict.find(cmd);
464 if (pos != m_user_dict.end())
465 ret_val = pos->second;
466 }
467
Sean Callananb386d822012-08-09 00:50:26 +0000468 if (!exact && !ret_val)
Chris Lattner24943d22010-06-08 16:52:24 +0000469 {
Jim Inghamd40f8a62010-07-06 22:46:59 +0000470 // We will only get into here if we didn't find any exact matches.
471
472 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
473
Chris Lattner24943d22010-06-08 16:52:24 +0000474 StringList local_matches;
475 if (matches == NULL)
476 matches = &local_matches;
477
Jim Inghamd40f8a62010-07-06 22:46:59 +0000478 unsigned int num_cmd_matches = 0;
479 unsigned int num_alias_matches = 0;
480 unsigned int num_user_matches = 0;
481
482 // Look through the command dictionaries one by one, and if we get only one match from any of
483 // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
484
Chris Lattner24943d22010-06-08 16:52:24 +0000485 if (HasCommands())
486 {
487 num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
488 }
489
490 if (num_cmd_matches == 1)
491 {
492 cmd.assign(matches->GetStringAtIndex(0));
493 pos = m_command_dict.find(cmd);
494 if (pos != m_command_dict.end())
Jim Inghamd40f8a62010-07-06 22:46:59 +0000495 real_match_sp = pos->second;
Chris Lattner24943d22010-06-08 16:52:24 +0000496 }
497
Jim Ingham9a574172010-06-24 20:28:42 +0000498 if (include_aliases && HasAliases())
Chris Lattner24943d22010-06-08 16:52:24 +0000499 {
500 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
501
502 }
503
Jim Inghamd40f8a62010-07-06 22:46:59 +0000504 if (num_alias_matches == 1)
Chris Lattner24943d22010-06-08 16:52:24 +0000505 {
506 cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
507 pos = m_alias_dict.find(cmd);
508 if (pos != m_alias_dict.end())
Jim Inghamd40f8a62010-07-06 22:46:59 +0000509 alias_match_sp = pos->second;
Chris Lattner24943d22010-06-08 16:52:24 +0000510 }
511
Jim Ingham9a574172010-06-24 20:28:42 +0000512 if (HasUserCommands())
Chris Lattner24943d22010-06-08 16:52:24 +0000513 {
514 num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
515 }
516
Jim Inghamd40f8a62010-07-06 22:46:59 +0000517 if (num_user_matches == 1)
Chris Lattner24943d22010-06-08 16:52:24 +0000518 {
519 cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
520
521 pos = m_user_dict.find (cmd);
522 if (pos != m_user_dict.end())
Jim Inghamd40f8a62010-07-06 22:46:59 +0000523 user_match_sp = pos->second;
524 }
525
526 // If we got exactly one match, return that, otherwise return the match list.
527
528 if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
529 {
530 if (num_cmd_matches)
531 return real_match_sp;
532 else if (num_alias_matches)
533 return alias_match_sp;
534 else
535 return user_match_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000536 }
537 }
Sean Callananb386d822012-08-09 00:50:26 +0000538 else if (matches && ret_val)
Jim Inghamd40f8a62010-07-06 22:46:59 +0000539 {
540 matches->AppendString (cmd_cstr);
Chris Lattner24943d22010-06-08 16:52:24 +0000541 }
542
543
544 return ret_val;
545}
546
Greg Claytond12aeab2011-04-20 16:37:46 +0000547bool
548CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
549{
550 if (name && name[0])
551 {
552 std::string name_sstr(name);
553 if (!can_replace)
554 {
555 if (m_command_dict.find (name_sstr) != m_command_dict.end())
556 return false;
557 }
558 m_command_dict[name_sstr] = cmd_sp;
559 return true;
560 }
561 return false;
562}
563
Enrico Granata6b1596d2011-08-16 23:24:13 +0000564bool
Enrico Granata6010ace2011-11-07 22:57:04 +0000565CommandInterpreter::AddUserCommand (std::string name,
Enrico Granata6b1596d2011-08-16 23:24:13 +0000566 const lldb::CommandObjectSP &cmd_sp,
567 bool can_replace)
568{
Enrico Granata6010ace2011-11-07 22:57:04 +0000569 if (!name.empty())
Enrico Granata6b1596d2011-08-16 23:24:13 +0000570 {
Enrico Granata6010ace2011-11-07 22:57:04 +0000571
572 const char* name_cstr = name.c_str();
573
574 // do not allow replacement of internal commands
575 if (CommandExists(name_cstr))
576 return false;
577
578 if (can_replace == false && UserCommandExists(name_cstr))
579 return false;
580
581 m_user_dict[name] = cmd_sp;
Enrico Granata6b1596d2011-08-16 23:24:13 +0000582 return true;
583 }
584 return false;
585}
Greg Claytond12aeab2011-04-20 16:37:46 +0000586
Jim Inghamd40f8a62010-07-06 22:46:59 +0000587CommandObjectSP
588CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
Chris Lattner24943d22010-06-08 16:52:24 +0000589{
Caroline Tice56d2fc42010-12-14 18:51:39 +0000590 Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
591 CommandObjectSP ret_val; // Possibly empty return value.
592
593 if (cmd_cstr == NULL)
594 return ret_val;
595
596 if (cmd_words.GetArgumentCount() == 1)
597 return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
598 else
599 {
600 // We have a multi-word command (seemingly), so we need to do more work.
601 // First, get the cmd_obj_sp for the first word in the command.
602 CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL);
603 if (cmd_obj_sp.get() != NULL)
604 {
605 // Loop through the rest of the words in the command (everything passed in was supposed to be part of a
606 // command name), and find the appropriate sub-command SP for each command word....
607 size_t end = cmd_words.GetArgumentCount();
608 for (size_t j= 1; j < end; ++j)
609 {
610 if (cmd_obj_sp->IsMultiwordObject())
611 {
612 cmd_obj_sp = ((CommandObjectMultiword *) cmd_obj_sp.get())->GetSubcommandSP
613 (cmd_words.GetArgumentAtIndex (j));
614 if (cmd_obj_sp.get() == NULL)
615 // The sub-command name was invalid. Fail and return the empty 'ret_val'.
616 return ret_val;
617 }
618 else
619 // We have more words in the command name, but we don't have a multiword object. Fail and return
620 // empty 'ret_val'.
621 return ret_val;
622 }
623 // We successfully looped through all the command words and got valid command objects for them. Assign the
624 // last object retrieved to 'ret_val'.
625 ret_val = cmd_obj_sp;
626 }
627 }
628 return ret_val;
Jim Inghamd40f8a62010-07-06 22:46:59 +0000629}
630
631CommandObject *
632CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
633{
634 return GetCommandSPExact (cmd_cstr, include_aliases).get();
635}
636
637CommandObject *
638CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
639{
640 CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
641
642 // If we didn't find an exact match to the command string in the commands, look in
643 // the aliases.
644
645 if (command_obj == NULL)
646 {
647 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
648 }
649
650 // Finally, if there wasn't an exact match among the aliases, look for an inexact match
651 // in both the commands and the aliases.
652
653 if (command_obj == NULL)
654 command_obj = GetCommandSP(cmd_cstr, true, false, matches).get();
655
656 return command_obj;
Chris Lattner24943d22010-06-08 16:52:24 +0000657}
658
659bool
660CommandInterpreter::CommandExists (const char *cmd)
661{
662 return m_command_dict.find(cmd) != m_command_dict.end();
663}
664
665bool
Caroline Tice5ddbe212011-05-06 21:37:15 +0000666CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
667 const char *options_args,
668 OptionArgVectorSP &option_arg_vector_sp)
669{
670 bool success = true;
671 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
672
673 if (!options_args || (strlen (options_args) < 1))
674 return true;
675
676 std::string options_string (options_args);
677 Args args (options_args);
678 CommandReturnObject result;
679 // Check to see if the command being aliased can take any command options.
680 Options *options = cmd_obj_sp->GetOptions ();
681 if (options)
682 {
683 // See if any options were specified as part of the alias; if so, handle them appropriately.
684 options->NotifyOptionParsingStarting ();
685 args.Unshift ("dummy_arg");
686 args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
687 args.Shift ();
688 if (result.Succeeded())
689 options->VerifyPartialOptions (result);
690 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
691 {
692 result.AppendError ("Unable to create requested alias.\n");
693 return false;
694 }
695 }
696
Greg Clayton7268b4c2011-10-28 21:38:01 +0000697 if (!options_string.empty())
Caroline Tice5ddbe212011-05-06 21:37:15 +0000698 {
699 if (cmd_obj_sp->WantsRawCommandString ())
700 option_arg_vector->push_back (OptionArgPair ("<argument>",
701 OptionArgValue (-1,
702 options_string)));
703 else
704 {
705 int argc = args.GetArgumentCount();
706 for (size_t i = 0; i < argc; ++i)
707 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
708 option_arg_vector->push_back
709 (OptionArgPair ("<argument>",
710 OptionArgValue (-1,
711 std::string (args.GetArgumentAtIndex (i)))));
712 }
713 }
714
715 return success;
716}
717
718bool
Chris Lattner24943d22010-06-08 16:52:24 +0000719CommandInterpreter::AliasExists (const char *cmd)
720{
721 return m_alias_dict.find(cmd) != m_alias_dict.end();
722}
723
724bool
725CommandInterpreter::UserCommandExists (const char *cmd)
726{
727 return m_user_dict.find(cmd) != m_user_dict.end();
728}
729
730void
731CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
732{
Jim Inghamd40f8a62010-07-06 22:46:59 +0000733 command_obj_sp->SetIsAlias (true);
Chris Lattner24943d22010-06-08 16:52:24 +0000734 m_alias_dict[alias_name] = command_obj_sp;
735}
736
737bool
738CommandInterpreter::RemoveAlias (const char *alias_name)
739{
740 CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
741 if (pos != m_alias_dict.end())
742 {
743 m_alias_dict.erase(pos);
744 return true;
745 }
746 return false;
747}
748bool
749CommandInterpreter::RemoveUser (const char *alias_name)
750{
751 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
752 if (pos != m_user_dict.end())
753 {
754 m_user_dict.erase(pos);
755 return true;
756 }
757 return false;
758}
759
Chris Lattner24943d22010-06-08 16:52:24 +0000760void
761CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
762{
763 help_string.Printf ("'%s", command_name);
764 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
765
Sean Callananb386d822012-08-09 00:50:26 +0000766 if (option_arg_vector_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000767 {
768 OptionArgVector *options = option_arg_vector_sp.get();
769 for (int i = 0; i < options->size(); ++i)
770 {
771 OptionArgPair cur_option = (*options)[i];
772 std::string opt = cur_option.first;
Caroline Tice44c841d2010-12-07 19:58:26 +0000773 OptionArgValue value_pair = cur_option.second;
774 std::string value = value_pair.second;
Chris Lattner24943d22010-06-08 16:52:24 +0000775 if (opt.compare("<argument>") == 0)
776 {
777 help_string.Printf (" %s", value.c_str());
778 }
779 else
780 {
781 help_string.Printf (" %s", opt.c_str());
782 if ((value.compare ("<no-argument>") != 0)
783 && (value.compare ("<need-argument") != 0))
784 {
785 help_string.Printf (" %s", value.c_str());
786 }
787 }
788 }
789 }
790
791 help_string.Printf ("'");
792}
793
Greg Clayton65124ea2010-08-26 22:05:43 +0000794size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000795CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
796{
797 CommandObject::CommandMap::const_iterator pos;
Greg Clayton65124ea2010-08-26 22:05:43 +0000798 CommandObject::CommandMap::const_iterator end = dict.end();
799 size_t max_len = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000800
Greg Clayton65124ea2010-08-26 22:05:43 +0000801 for (pos = dict.begin(); pos != end; ++pos)
802 {
803 size_t len = pos->first.size();
804 if (max_len < len)
805 max_len = len;
Chris Lattner24943d22010-06-08 16:52:24 +0000806 }
Greg Clayton65124ea2010-08-26 22:05:43 +0000807 return max_len;
Chris Lattner24943d22010-06-08 16:52:24 +0000808}
809
810void
Enrico Granata6b1596d2011-08-16 23:24:13 +0000811CommandInterpreter::GetHelp (CommandReturnObject &result,
Enrico Granata1ac6d1f2011-09-09 17:49:36 +0000812 uint32_t cmd_types)
Chris Lattner24943d22010-06-08 16:52:24 +0000813{
814 CommandObject::CommandMap::const_iterator pos;
Greg Clayton65124ea2010-08-26 22:05:43 +0000815 uint32_t max_len = FindLongestCommandWord (m_command_dict);
Enrico Granata6b1596d2011-08-16 23:24:13 +0000816
817 if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
Chris Lattner24943d22010-06-08 16:52:24 +0000818 {
Enrico Granata6b1596d2011-08-16 23:24:13 +0000819
820 result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
821 result.AppendMessage("");
Chris Lattner24943d22010-06-08 16:52:24 +0000822
Enrico Granata6b1596d2011-08-16 23:24:13 +0000823 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
824 {
825 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
826 max_len);
827 }
828 result.AppendMessage("");
829
830 }
831
Greg Clayton7268b4c2011-10-28 21:38:01 +0000832 if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
Chris Lattner24943d22010-06-08 16:52:24 +0000833 {
Jim Inghame3663e82010-10-22 18:47:16 +0000834 result.AppendMessage("The following is a list of your current command abbreviations "
Johnny Chen9e4c3d72011-04-21 00:39:18 +0000835 "(see 'help command alias' for more info):");
Chris Lattner24943d22010-06-08 16:52:24 +0000836 result.AppendMessage("");
Greg Clayton65124ea2010-08-26 22:05:43 +0000837 max_len = FindLongestCommandWord (m_alias_dict);
838
Chris Lattner24943d22010-06-08 16:52:24 +0000839 for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
840 {
841 StreamString sstr;
842 StreamString translation_and_help;
843 std::string entry_name = pos->first;
844 std::string second_entry = pos->second.get()->GetCommandName();
845 GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
846
847 translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp());
848 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
849 translation_and_help.GetData(), max_len);
850 }
851 result.AppendMessage("");
852 }
853
Greg Clayton7268b4c2011-10-28 21:38:01 +0000854 if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
Chris Lattner24943d22010-06-08 16:52:24 +0000855 {
856 result.AppendMessage ("The following is a list of your current user-defined commands:");
857 result.AppendMessage("");
Enrico Granata6b1596d2011-08-16 23:24:13 +0000858 max_len = FindLongestCommandWord (m_user_dict);
Chris Lattner24943d22010-06-08 16:52:24 +0000859 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
860 {
Enrico Granata6b1596d2011-08-16 23:24:13 +0000861 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
862 max_len);
Chris Lattner24943d22010-06-08 16:52:24 +0000863 }
864 result.AppendMessage("");
865 }
866
867 result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
868}
869
Caroline Ticee0da7a52010-12-09 22:52:49 +0000870CommandObject *
871CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
Chris Lattner24943d22010-06-08 16:52:24 +0000872{
Caroline Ticee0da7a52010-12-09 22:52:49 +0000873 // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
874 // eventually be invoked by the given command line.
875
876 CommandObject *cmd_obj = NULL;
877 std::string white_space (" \t\v");
878 size_t start = command_string.find_first_not_of (white_space);
879 size_t end = 0;
880 bool done = false;
881 while (!done)
882 {
883 if (start != std::string::npos)
884 {
885 // Get the next word from command_string.
886 end = command_string.find_first_of (white_space, start);
887 if (end == std::string::npos)
888 end = command_string.size();
889 std::string cmd_word = command_string.substr (start, end - start);
890
891 if (cmd_obj == NULL)
892 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
893 // command or alias.
894 cmd_obj = GetCommandObject (cmd_word.c_str());
895 else if (cmd_obj->IsMultiwordObject ())
896 {
897 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
898 CommandObject *sub_cmd_obj =
899 ((CommandObjectMultiword *) cmd_obj)->GetSubcommandObject (cmd_word.c_str());
900 if (sub_cmd_obj)
901 cmd_obj = sub_cmd_obj;
902 else // cmd_word was not a valid sub-command word, so we are donee
903 done = true;
904 }
905 else
906 // We have a cmd_obj and it is not a multi-word object, so we are done.
907 done = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000908
Caroline Ticee0da7a52010-12-09 22:52:49 +0000909 // If we didn't find a valid command object, or our command object is not a multi-word object, or
910 // we are at the end of the command_string, then we are done. Otherwise, find the start of the
911 // next word.
912
913 if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
914 done = true;
915 else
916 start = command_string.find_first_not_of (white_space, end);
917 }
918 else
919 // Unable to find any more words.
920 done = true;
921 }
922
923 if (end == command_string.size())
924 command_string.clear();
925 else
926 command_string = command_string.substr(end);
927
928 return cmd_obj;
929}
930
Greg Clayton9d855c62011-10-25 00:36:27 +0000931static const char *k_white_space = " \t\v";
Greg Clayton7268b4c2011-10-28 21:38:01 +0000932static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
Greg Clayton9d855c62011-10-25 00:36:27 +0000933static void
934StripLeadingSpaces (std::string &s)
Caroline Ticee0da7a52010-12-09 22:52:49 +0000935{
Greg Clayton9d855c62011-10-25 00:36:27 +0000936 if (!s.empty())
Caroline Ticee0da7a52010-12-09 22:52:49 +0000937 {
Greg Clayton9d855c62011-10-25 00:36:27 +0000938 size_t pos = s.find_first_not_of (k_white_space);
939 if (pos == std::string::npos)
940 s.clear();
941 else if (pos == 0)
942 return;
943 s.erase (0, pos);
944 }
945}
946
Greg Clayton3840cd72011-11-09 23:25:03 +0000947static size_t
948FindArgumentTerminator (const std::string &s)
949{
Greg Clayton3840cd72011-11-09 23:25:03 +0000950 const size_t s_len = s.size();
951 size_t offset = 0;
952 while (offset < s_len)
953 {
954 size_t pos = s.find ("--", offset);
955 if (pos == std::string::npos)
956 break;
957 if (pos > 0)
958 {
959 if (isspace(s[pos-1]))
960 {
961 // Check if the string ends "\s--" (where \s is a space character)
962 // or if we have "\s--\s".
963 if ((pos + 2 >= s_len) || isspace(s[pos+2]))
964 {
Greg Clayton3840cd72011-11-09 23:25:03 +0000965 return pos;
966 }
967 }
968 }
969 offset = pos + 2;
970 }
Greg Clayton3840cd72011-11-09 23:25:03 +0000971 return std::string::npos;
972}
973
Greg Clayton9d855c62011-10-25 00:36:27 +0000974static bool
Greg Clayton7268b4c2011-10-28 21:38:01 +0000975ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char &quote_char)
Greg Clayton9d855c62011-10-25 00:36:27 +0000976{
Greg Clayton7268b4c2011-10-28 21:38:01 +0000977 command.clear();
978 suffix.clear();
Greg Clayton9d855c62011-10-25 00:36:27 +0000979 StripLeadingSpaces (command_string);
980
981 bool result = false;
982 quote_char = '\0';
983
984 if (!command_string.empty())
985 {
986 const char first_char = command_string[0];
987 if (first_char == '\'' || first_char == '"')
Caroline Ticee0da7a52010-12-09 22:52:49 +0000988 {
Greg Clayton9d855c62011-10-25 00:36:27 +0000989 quote_char = first_char;
990 const size_t end_quote_pos = command_string.find (quote_char, 1);
991 if (end_quote_pos == std::string::npos)
Caroline Tice649116c2011-05-11 16:07:06 +0000992 {
Greg Clayton7268b4c2011-10-28 21:38:01 +0000993 command.swap (command_string);
Greg Clayton9d855c62011-10-25 00:36:27 +0000994 command_string.erase ();
Caroline Tice649116c2011-05-11 16:07:06 +0000995 }
996 else
997 {
Greg Clayton7268b4c2011-10-28 21:38:01 +0000998 command.assign (command_string, 1, end_quote_pos - 1);
Greg Clayton9d855c62011-10-25 00:36:27 +0000999 if (end_quote_pos + 1 < command_string.size())
1000 command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
1001 else
1002 command_string.erase ();
Caroline Tice649116c2011-05-11 16:07:06 +00001003 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001004 }
1005 else
1006 {
Greg Clayton9d855c62011-10-25 00:36:27 +00001007 const size_t first_space_pos = command_string.find_first_of (k_white_space);
1008 if (first_space_pos == std::string::npos)
Caroline Tice649116c2011-05-11 16:07:06 +00001009 {
Greg Clayton7268b4c2011-10-28 21:38:01 +00001010 command.swap (command_string);
Greg Clayton9d855c62011-10-25 00:36:27 +00001011 command_string.erase();
Caroline Tice649116c2011-05-11 16:07:06 +00001012 }
1013 else
1014 {
Greg Clayton7268b4c2011-10-28 21:38:01 +00001015 command.assign (command_string, 0, first_space_pos);
1016 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
Caroline Tice649116c2011-05-11 16:07:06 +00001017 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001018 }
Greg Clayton9d855c62011-10-25 00:36:27 +00001019 result = true;
Caroline Ticee0da7a52010-12-09 22:52:49 +00001020 }
Greg Clayton7268b4c2011-10-28 21:38:01 +00001021
1022
1023 if (!command.empty())
1024 {
1025 // actual commands can't start with '-' or '_'
1026 if (command[0] != '-' && command[0] != '_')
1027 {
1028 size_t pos = command.find_first_not_of(k_valid_command_chars);
1029 if (pos > 0 && pos != std::string::npos)
1030 {
1031 suffix.assign (command.begin() + pos, command.end());
1032 command.erase (pos);
1033 }
1034 }
1035 }
Greg Clayton9d855c62011-10-25 00:36:27 +00001036
1037 return result;
Caroline Ticee0da7a52010-12-09 22:52:49 +00001038}
1039
Greg Clayton7268b4c2011-10-28 21:38:01 +00001040CommandObject *
1041CommandInterpreter::BuildAliasResult (const char *alias_name,
1042 std::string &raw_input_string,
1043 std::string &alias_result,
1044 CommandReturnObject &result)
Caroline Ticee0da7a52010-12-09 22:52:49 +00001045{
Greg Clayton7268b4c2011-10-28 21:38:01 +00001046 CommandObject *alias_cmd_obj = NULL;
Caroline Ticee0da7a52010-12-09 22:52:49 +00001047 Args cmd_args (raw_input_string.c_str());
1048 alias_cmd_obj = GetCommandObject (alias_name);
1049 StreamString result_str;
1050
1051 if (alias_cmd_obj)
1052 {
1053 std::string alias_name_str = alias_name;
1054 if ((cmd_args.GetArgumentCount() == 0)
1055 || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
1056 cmd_args.Unshift (alias_name);
1057
1058 result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
1059 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1060
1061 if (option_arg_vector_sp.get())
1062 {
1063 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1064
1065 for (int i = 0; i < option_arg_vector->size(); ++i)
1066 {
1067 OptionArgPair option_pair = (*option_arg_vector)[i];
1068 OptionArgValue value_pair = option_pair.second;
1069 int value_type = value_pair.first;
1070 std::string option = option_pair.first;
1071 std::string value = value_pair.second;
1072 if (option.compare ("<argument>") == 0)
1073 result_str.Printf (" %s", value.c_str());
1074 else
1075 {
1076 result_str.Printf (" %s", option.c_str());
1077 if (value_type != optional_argument)
1078 result_str.Printf (" ");
1079 if (value.compare ("<no_argument>") != 0)
1080 {
1081 int index = GetOptionArgumentPosition (value.c_str());
1082 if (index == 0)
1083 result_str.Printf ("%s", value.c_str());
1084 else if (index >= cmd_args.GetArgumentCount())
1085 {
1086
1087 result.AppendErrorWithFormat
1088 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
1089 index);
1090 result.SetStatus (eReturnStatusFailed);
Greg Clayton7268b4c2011-10-28 21:38:01 +00001091 return alias_cmd_obj;
Caroline Ticee0da7a52010-12-09 22:52:49 +00001092 }
1093 else
1094 {
1095 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
1096 if (strpos != std::string::npos)
1097 raw_input_string = raw_input_string.erase (strpos,
1098 strlen (cmd_args.GetArgumentAtIndex (index)));
1099 result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
1100 }
1101 }
1102 }
1103 }
1104 }
1105
1106 alias_result = result_str.GetData();
1107 }
Greg Clayton7268b4c2011-10-28 21:38:01 +00001108 return alias_cmd_obj;
Caroline Ticee0da7a52010-12-09 22:52:49 +00001109}
1110
Greg Claytonf5c0c722011-10-14 07:41:33 +00001111Error
1112CommandInterpreter::PreprocessCommand (std::string &command)
1113{
1114 // The command preprocessor needs to do things to the command
1115 // line before any parsing of arguments or anything else is done.
1116 // The only current stuff that gets proprocessed is anyting enclosed
1117 // in backtick ('`') characters is evaluated as an expression and
1118 // the result of the expression must be a scalar that can be substituted
1119 // into the command. An example would be:
1120 // (lldb) memory read `$rsp + 20`
1121 Error error; // Error for any expressions that might not evaluate
1122 size_t start_backtick;
1123 size_t pos = 0;
1124 while ((start_backtick = command.find ('`', pos)) != std::string::npos)
1125 {
1126 if (start_backtick > 0 && command[start_backtick-1] == '\\')
1127 {
1128 // The backtick was preceeded by a '\' character, remove the slash
1129 // and don't treat the backtick as the start of an expression
1130 command.erase(start_backtick-1, 1);
1131 // No need to add one to start_backtick since we just deleted a char
1132 pos = start_backtick;
1133 }
1134 else
1135 {
1136 const size_t expr_content_start = start_backtick + 1;
1137 const size_t end_backtick = command.find ('`', expr_content_start);
1138 if (end_backtick == std::string::npos)
1139 return error;
1140 else if (end_backtick == expr_content_start)
1141 {
1142 // Empty expression (two backticks in a row)
1143 command.erase (start_backtick, 2);
1144 }
1145 else
1146 {
1147 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
1148
Greg Claytonbcaf99a2012-07-12 20:32:19 +00001149 ExecutionContext exe_ctx(GetExecutionContext());
1150 Target *target = exe_ctx.GetTargetPtr();
Johnny Chenb09f8472011-10-29 00:21:50 +00001151 // Get a dummy target to allow for calculator mode while processing backticks.
1152 // This also helps break the infinite loop caused when target is null.
1153 if (!target)
1154 target = Host::GetDummyTarget(GetDebugger()).get();
Greg Claytonf5c0c722011-10-14 07:41:33 +00001155 if (target)
1156 {
Sean Callanandaa6efe2011-12-21 22:22:58 +00001157 const bool coerce_to_id = false;
Greg Claytonf5c0c722011-10-14 07:41:33 +00001158 const bool unwind_on_error = true;
1159 const bool keep_in_memory = false;
1160 ValueObjectSP expr_result_valobj_sp;
1161 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
Greg Claytonbcaf99a2012-07-12 20:32:19 +00001162 exe_ctx.GetFramePtr(),
Greg Claytonf5c0c722011-10-14 07:41:33 +00001163 eExecutionPolicyOnlyWhenNeeded,
Sean Callanandaa6efe2011-12-21 22:22:58 +00001164 coerce_to_id,
1165 unwind_on_error,
1166 keep_in_memory,
Greg Claytonf5c0c722011-10-14 07:41:33 +00001167 eNoDynamicValues,
Enrico Granata6cca9692012-07-16 23:10:35 +00001168 expr_result_valobj_sp,
1169 0 /* no timeout */);
Greg Claytonf5c0c722011-10-14 07:41:33 +00001170 if (expr_result == eExecutionCompleted)
1171 {
1172 Scalar scalar;
1173 if (expr_result_valobj_sp->ResolveValue (scalar))
1174 {
1175 command.erase (start_backtick, end_backtick - start_backtick + 1);
1176 StreamString value_strm;
1177 const bool show_type = false;
1178 scalar.GetValue (&value_strm, show_type);
1179 size_t value_string_size = value_strm.GetSize();
1180 if (value_string_size)
1181 {
1182 command.insert (start_backtick, value_strm.GetData(), value_string_size);
1183 pos = start_backtick + value_string_size;
1184 continue;
1185 }
1186 else
1187 {
1188 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1189 }
1190 }
1191 else
1192 {
1193 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1194 }
1195 }
1196 else
1197 {
1198 if (expr_result_valobj_sp)
1199 error = expr_result_valobj_sp->GetError();
1200 if (error.Success())
1201 {
1202
1203 switch (expr_result)
1204 {
1205 case eExecutionSetupError:
1206 error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
1207 break;
1208 case eExecutionCompleted:
1209 break;
1210 case eExecutionDiscarded:
1211 error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
1212 break;
1213 case eExecutionInterrupted:
1214 error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
1215 break;
1216 case eExecutionTimedOut:
1217 error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
1218 break;
1219 }
1220 }
1221 }
1222 }
1223 }
1224 if (error.Fail())
1225 break;
1226 }
1227 }
1228 return error;
1229}
1230
1231
Caroline Ticee0da7a52010-12-09 22:52:49 +00001232bool
1233CommandInterpreter::HandleCommand (const char *command_line,
Enrico Granata01bc2d42012-05-31 01:09:06 +00001234 LazyBool lazy_add_to_history,
Caroline Ticee0da7a52010-12-09 22:52:49 +00001235 CommandReturnObject &result,
Jim Ingham949d5ac2011-02-18 00:54:25 +00001236 ExecutionContext *override_context,
Johnny Chen8bdf57c2011-10-05 00:42:59 +00001237 bool repeat_on_empty_command,
1238 bool no_context_switching)
Jim Ingham949d5ac2011-02-18 00:54:25 +00001239
Caroline Ticee0da7a52010-12-09 22:52:49 +00001240{
Jim Ingham949d5ac2011-02-18 00:54:25 +00001241
Caroline Ticee0da7a52010-12-09 22:52:49 +00001242 bool done = false;
1243 CommandObject *cmd_obj = NULL;
Caroline Ticee0da7a52010-12-09 22:52:49 +00001244 bool wants_raw_input = false;
1245 std::string command_string (command_line);
Jim Ingham6247dbe2011-07-12 03:12:18 +00001246 std::string original_command_string (command_line);
Caroline Ticee0da7a52010-12-09 22:52:49 +00001247
1248 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
Greg Claytone98ac252010-11-10 04:57:04 +00001249 Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
1250
1251 // Make a scoped cleanup object that will clear the crash description string
1252 // on exit of this function.
Enrico Granata1a102082011-07-12 00:18:11 +00001253 lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription);
Greg Claytone98ac252010-11-10 04:57:04 +00001254
Caroline Ticee0da7a52010-12-09 22:52:49 +00001255 if (log)
1256 log->Printf ("Processing command: %s", command_line);
Chris Lattner24943d22010-06-08 16:52:24 +00001257
Jim Inghamabab14b2010-11-04 23:08:45 +00001258 Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
1259
Johnny Chen8bdf57c2011-10-05 00:42:59 +00001260 if (!no_context_switching)
1261 UpdateExecutionContext (override_context);
Enrico Granata01bc2d42012-05-31 01:09:06 +00001262
1263 // <rdar://problem/11328896>
1264 bool add_to_history;
1265 if (lazy_add_to_history == eLazyBoolCalculate)
1266 add_to_history = (m_command_source_depth == 0);
1267 else
1268 add_to_history = (lazy_add_to_history == eLazyBoolYes);
1269
Jim Ingham949d5ac2011-02-18 00:54:25 +00001270 bool empty_command = false;
1271 bool comment_command = false;
1272 if (command_string.empty())
1273 empty_command = true;
1274 else
Chris Lattner24943d22010-06-08 16:52:24 +00001275 {
Jim Ingham949d5ac2011-02-18 00:54:25 +00001276 const char *k_space_characters = "\t\n\v\f\r ";
1277
1278 size_t non_space = command_string.find_first_not_of (k_space_characters);
1279 // Check for empty line or comment line (lines whose first
1280 // non-space character is the comment character for this interpreter)
1281 if (non_space == std::string::npos)
1282 empty_command = true;
1283 else if (command_string[non_space] == m_comment_char)
1284 comment_command = true;
Jim Ingham6247dbe2011-07-12 03:12:18 +00001285 else if (command_string[non_space] == m_repeat_char)
1286 {
1287 const char *history_string = FindHistoryString (command_string.c_str() + non_space);
1288 if (history_string == NULL)
1289 {
1290 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
1291 result.SetStatus(eReturnStatusFailed);
1292 return false;
1293 }
1294 add_to_history = false;
1295 command_string = history_string;
1296 original_command_string = history_string;
1297 }
Jim Ingham949d5ac2011-02-18 00:54:25 +00001298 }
1299
1300 if (empty_command)
1301 {
1302 if (repeat_on_empty_command)
Chris Lattner24943d22010-06-08 16:52:24 +00001303 {
Jim Ingham949d5ac2011-02-18 00:54:25 +00001304 if (m_command_history.empty())
1305 {
1306 result.AppendError ("empty command");
1307 result.SetStatus(eReturnStatusFailed);
1308 return false;
1309 }
1310 else
1311 {
1312 command_line = m_repeat_command.c_str();
1313 command_string = command_line;
Jim Ingham6247dbe2011-07-12 03:12:18 +00001314 original_command_string = command_line;
Jim Ingham949d5ac2011-02-18 00:54:25 +00001315 if (m_repeat_command.empty())
1316 {
1317 result.AppendErrorWithFormat("No auto repeat.\n");
1318 result.SetStatus (eReturnStatusFailed);
1319 return false;
1320 }
1321 }
1322 add_to_history = false;
Chris Lattner24943d22010-06-08 16:52:24 +00001323 }
1324 else
1325 {
Jim Ingham949d5ac2011-02-18 00:54:25 +00001326 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1327 return true;
Chris Lattner24943d22010-06-08 16:52:24 +00001328 }
Jim Ingham949d5ac2011-02-18 00:54:25 +00001329 }
1330 else if (comment_command)
1331 {
1332 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1333 return true;
Chris Lattner24943d22010-06-08 16:52:24 +00001334 }
Caroline Tice649116c2011-05-11 16:07:06 +00001335
Greg Claytonf5c0c722011-10-14 07:41:33 +00001336
1337 Error error (PreprocessCommand (command_string));
1338
1339 if (error.Fail())
1340 {
1341 result.AppendError (error.AsCString());
1342 result.SetStatus(eReturnStatusFailed);
1343 return false;
1344 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001345 // Phase 1.
1346
1347 // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
1348 // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that
1349 // the user could have specified an alias, and in translating the alias there may also be command options and/or
1350 // even data (including raw text strings) that need to be found and inserted into the command line as part of
1351 // 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 +00001352 // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
Caroline Ticee0da7a52010-12-09 22:52:49 +00001353 // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
Caroline Tice44c841d2010-12-07 19:58:26 +00001354
Caroline Ticee0da7a52010-12-09 22:52:49 +00001355 StreamString revised_command_line;
Caroline Ticeea6e3df2010-12-11 08:16:56 +00001356 size_t actual_cmd_name_len = 0;
Greg Clayton7268b4c2011-10-28 21:38:01 +00001357 std::string next_word;
Filipe Cabecinhas4bc8d162012-05-16 23:25:54 +00001358 StringList matches;
Caroline Ticee0da7a52010-12-09 22:52:49 +00001359 while (!done)
Chris Lattner24943d22010-06-08 16:52:24 +00001360 {
Caroline Tice649116c2011-05-11 16:07:06 +00001361 char quote_char = '\0';
Greg Clayton7268b4c2011-10-28 21:38:01 +00001362 std::string suffix;
1363 ExtractCommand (command_string, next_word, suffix, quote_char);
1364 if (cmd_obj == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001365 {
Greg Clayton7268b4c2011-10-28 21:38:01 +00001366 if (AliasExists (next_word.c_str()))
Caroline Tice56d2fc42010-12-14 18:51:39 +00001367 {
Greg Clayton7268b4c2011-10-28 21:38:01 +00001368 std::string alias_result;
1369 cmd_obj = BuildAliasResult (next_word.c_str(), command_string, alias_result, result);
1370 revised_command_line.Printf ("%s", alias_result.c_str());
1371 if (cmd_obj)
1372 {
1373 wants_raw_input = cmd_obj->WantsRawCommandString ();
1374 actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
1375 }
Chris Lattner24943d22010-06-08 16:52:24 +00001376 }
1377 else
1378 {
Filipe Cabecinhas4bc8d162012-05-16 23:25:54 +00001379 cmd_obj = GetCommandObject (next_word.c_str(), &matches);
Greg Clayton7268b4c2011-10-28 21:38:01 +00001380 if (cmd_obj)
1381 {
1382 actual_cmd_name_len += next_word.length();
1383 revised_command_line.Printf ("%s", next_word.c_str());
1384 wants_raw_input = cmd_obj->WantsRawCommandString ();
1385 }
Caroline Tice649116c2011-05-11 16:07:06 +00001386 else
Greg Clayton7268b4c2011-10-28 21:38:01 +00001387 {
1388 revised_command_line.Printf ("%s", next_word.c_str());
1389 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001390 }
1391 }
1392 else
1393 {
Greg Clayton7268b4c2011-10-28 21:38:01 +00001394 if (cmd_obj->IsMultiwordObject ())
1395 {
1396 CommandObject *sub_cmd_obj = ((CommandObjectMultiword *) cmd_obj)->GetSubcommandObject (next_word.c_str());
1397 if (sub_cmd_obj)
1398 {
1399 actual_cmd_name_len += next_word.length() + 1;
1400 revised_command_line.Printf (" %s", next_word.c_str());
1401 cmd_obj = sub_cmd_obj;
1402 wants_raw_input = cmd_obj->WantsRawCommandString ();
1403 }
1404 else
1405 {
1406 if (quote_char)
1407 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1408 else
1409 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1410 done = true;
1411 }
1412 }
Caroline Tice649116c2011-05-11 16:07:06 +00001413 else
Greg Clayton7268b4c2011-10-28 21:38:01 +00001414 {
1415 if (quote_char)
1416 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1417 else
1418 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1419 done = true;
1420 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001421 }
1422
1423 if (cmd_obj == NULL)
1424 {
Filipe Cabecinhas4bc8d162012-05-16 23:25:54 +00001425 uint32_t num_matches = matches.GetSize();
1426 if (matches.GetSize() > 1) {
1427 std::string error_msg;
1428 error_msg.assign ("Ambiguous command '");
1429 error_msg.append(next_word.c_str());
1430 error_msg.append ("'.");
1431
1432 error_msg.append (" Possible matches:");
1433
1434 for (uint32_t i = 0; i < num_matches; ++i) {
1435 error_msg.append ("\n\t");
1436 error_msg.append (matches.GetStringAtIndex(i));
1437 }
1438 error_msg.append ("\n");
1439 result.AppendRawError (error_msg.c_str(), error_msg.size());
1440 } else {
1441 // We didn't have only one match, otherwise we wouldn't get here.
1442 assert(num_matches == 0);
1443 result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
1444 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001445 result.SetStatus (eReturnStatusFailed);
1446 return false;
1447 }
1448
Greg Clayton7268b4c2011-10-28 21:38:01 +00001449 if (cmd_obj->IsMultiwordObject ())
1450 {
1451 if (!suffix.empty())
1452 {
1453
1454 result.AppendErrorWithFormat ("multi-word commands ('%s') can't have shorthand suffixes: '%s'\n",
1455 next_word.c_str(),
1456 suffix.c_str());
1457 result.SetStatus (eReturnStatusFailed);
1458 return false;
1459 }
1460 }
1461 else
1462 {
1463 // If we found a normal command, we are done
1464 done = true;
1465 if (!suffix.empty())
1466 {
1467 switch (suffix[0])
1468 {
1469 case '/':
1470 // GDB format suffixes
Greg Claytond8a218d2011-10-29 00:57:28 +00001471 {
1472 Options *command_options = cmd_obj->GetOptions();
1473 if (command_options && command_options->SupportsLongOption("gdb-format"))
1474 {
Greg Clayton3840cd72011-11-09 23:25:03 +00001475 std::string gdb_format_option ("--gdb-format=");
1476 gdb_format_option += (suffix.c_str() + 1);
1477
1478 bool inserted = false;
1479 std::string &cmd = revised_command_line.GetString();
1480 size_t arg_terminator_idx = FindArgumentTerminator (cmd);
1481 if (arg_terminator_idx != std::string::npos)
1482 {
1483 // Insert the gdb format option before the "--" that terminates options
1484 gdb_format_option.append(1,' ');
1485 cmd.insert(arg_terminator_idx, gdb_format_option);
1486 inserted = true;
1487 }
1488
1489 if (!inserted)
1490 revised_command_line.Printf (" %s", gdb_format_option.c_str());
1491
1492 if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
1493 revised_command_line.PutCString (" --");
Greg Claytond8a218d2011-10-29 00:57:28 +00001494 }
1495 else
1496 {
1497 result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n",
1498 cmd_obj->GetCommandName());
1499 result.SetStatus (eReturnStatusFailed);
1500 return false;
1501 }
1502 }
Greg Clayton7268b4c2011-10-28 21:38:01 +00001503 break;
Johnny Chen8ca450b2011-10-31 22:22:06 +00001504
1505 default:
1506 result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n",
1507 suffix.c_str());
1508 result.SetStatus (eReturnStatusFailed);
1509 return false;
1510
Greg Clayton7268b4c2011-10-28 21:38:01 +00001511 }
1512 }
1513 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001514 if (command_string.length() == 0)
1515 done = true;
1516
Chris Lattner24943d22010-06-08 16:52:24 +00001517 }
Caroline Ticee0da7a52010-12-09 22:52:49 +00001518
Greg Clayton7268b4c2011-10-28 21:38:01 +00001519 if (!command_string.empty())
Caroline Ticee0da7a52010-12-09 22:52:49 +00001520 revised_command_line.Printf (" %s", command_string.c_str());
1521
1522 // End of Phase 1.
1523 // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
1524 // specified was valid; revised_command_line contains the complete command line (including command name(s)),
1525 // fully translated with all substitutions & translations taken care of (still in raw text format); and
1526 // wants_raw_input specifies whether the Execute method expects raw input or not.
1527
1528
1529 if (log)
1530 {
1531 log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
1532 log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
1533 log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
1534 }
1535
1536 // Phase 2.
1537 // Take care of things like setting up the history command & calling the appropriate Execute method on the
1538 // CommandObject, with the appropriate arguments.
1539
1540 if (cmd_obj != NULL)
1541 {
1542 if (add_to_history)
1543 {
1544 Args command_args (revised_command_line.GetData());
1545 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
1546 if (repeat_command != NULL)
1547 m_repeat_command.assign(repeat_command);
1548 else
Jim Ingham6247dbe2011-07-12 03:12:18 +00001549 m_repeat_command.assign(original_command_string.c_str());
Caroline Ticee0da7a52010-12-09 22:52:49 +00001550
Jim Ingham6247dbe2011-07-12 03:12:18 +00001551 // Don't keep pushing the same command onto the history...
Greg Clayton7268b4c2011-10-28 21:38:01 +00001552 if (m_command_history.empty() || m_command_history.back() != original_command_string)
Jim Ingham6247dbe2011-07-12 03:12:18 +00001553 m_command_history.push_back (original_command_string);
Caroline Ticee0da7a52010-12-09 22:52:49 +00001554 }
1555
1556 command_string = revised_command_line.GetData();
1557 std::string command_name (cmd_obj->GetCommandName());
Caroline Ticeea6e3df2010-12-11 08:16:56 +00001558 std::string remainder;
1559 if (actual_cmd_name_len < command_string.length())
1560 remainder = command_string.substr (actual_cmd_name_len); // Note: 'actual_cmd_name_len' may be considerably shorter
1561 // than cmd_obj->GetCommandName(), because name completion
1562 // allows users to enter short versions of the names,
1563 // e.g. 'br s' for 'breakpoint set'.
Caroline Ticee0da7a52010-12-09 22:52:49 +00001564
1565 // Remove any initial spaces
1566 std::string white_space (" \t\v");
1567 size_t pos = remainder.find_first_not_of (white_space);
1568 if (pos != 0 && pos != std::string::npos)
Greg Clayton91c9dcf2011-04-22 20:58:45 +00001569 remainder.erase(0, pos);
Caroline Ticee0da7a52010-12-09 22:52:49 +00001570
1571 if (log)
Jason Molenda24c991c2011-08-25 00:20:04 +00001572 log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
Caroline Ticee0da7a52010-12-09 22:52:49 +00001573
Jim Inghamda26bd22012-06-08 21:56:10 +00001574 cmd_obj->Execute (remainder.c_str(), result);
Caroline Ticee0da7a52010-12-09 22:52:49 +00001575 }
1576 else
1577 {
1578 // We didn't find the first command object, so complete the first argument.
1579 Args command_args (revised_command_line.GetData());
1580 StringList matches;
1581 int num_matches;
1582 int cursor_index = 0;
1583 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
1584 bool word_complete;
1585 num_matches = HandleCompletionMatches (command_args,
1586 cursor_index,
1587 cursor_char_position,
1588 0,
1589 -1,
1590 word_complete,
1591 matches);
1592
1593 if (num_matches > 0)
1594 {
1595 std::string error_msg;
1596 error_msg.assign ("ambiguous command '");
1597 error_msg.append(command_args.GetArgumentAtIndex(0));
1598 error_msg.append ("'.");
1599
1600 error_msg.append (" Possible completions:");
1601 for (int i = 0; i < num_matches; i++)
1602 {
1603 error_msg.append ("\n\t");
1604 error_msg.append (matches.GetStringAtIndex (i));
1605 }
1606 error_msg.append ("\n");
1607 result.AppendRawError (error_msg.c_str(), error_msg.size());
1608 }
1609 else
1610 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
1611
1612 result.SetStatus (eReturnStatusFailed);
1613 }
1614
Jason Molenda24c991c2011-08-25 00:20:04 +00001615 if (log)
1616 log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
1617
Chris Lattner24943d22010-06-08 16:52:24 +00001618 return result.Succeeded();
1619}
1620
1621int
1622CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
1623 int &cursor_index,
1624 int &cursor_char_position,
1625 int match_start_point,
1626 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +00001627 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +00001628 StringList &matches)
1629{
1630 int num_command_matches = 0;
Chris Lattner24943d22010-06-08 16:52:24 +00001631 bool look_for_subcommand = false;
Jim Ingham802f8b02010-06-30 05:02:46 +00001632
1633 // For any of the command completions a unique match will be a complete word.
1634 word_complete = true;
Chris Lattner24943d22010-06-08 16:52:24 +00001635
1636 if (cursor_index == -1)
1637 {
1638 // We got nothing on the command line, so return the list of commands
Jim Inghamd40f8a62010-07-06 22:46:59 +00001639 bool include_aliases = true;
Chris Lattner24943d22010-06-08 16:52:24 +00001640 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
1641 }
1642 else if (cursor_index == 0)
1643 {
1644 // The cursor is in the first argument, so just do a lookup in the dictionary.
Jim Inghamd40f8a62010-07-06 22:46:59 +00001645 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
Chris Lattner24943d22010-06-08 16:52:24 +00001646 num_command_matches = matches.GetSize();
1647
1648 if (num_command_matches == 1
1649 && cmd_obj && cmd_obj->IsMultiwordObject()
1650 && matches.GetStringAtIndex(0) != NULL
1651 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
1652 {
1653 look_for_subcommand = true;
1654 num_command_matches = 0;
1655 matches.DeleteStringAtIndex(0);
1656 parsed_line.AppendArgument ("");
1657 cursor_index++;
1658 cursor_char_position = 0;
1659 }
1660 }
1661
1662 if (cursor_index > 0 || look_for_subcommand)
1663 {
1664 // We are completing further on into a commands arguments, so find the command and tell it
1665 // to complete the command.
1666 // First see if there is a matching initial command:
Jim Inghamd40f8a62010-07-06 22:46:59 +00001667 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
Chris Lattner24943d22010-06-08 16:52:24 +00001668 if (command_object == NULL)
1669 {
1670 return 0;
1671 }
1672 else
1673 {
1674 parsed_line.Shift();
1675 cursor_index--;
Greg Clayton238c0a12010-09-18 01:14:36 +00001676 num_command_matches = command_object->HandleCompletion (parsed_line,
Greg Clayton63094e02010-06-23 01:19:29 +00001677 cursor_index,
1678 cursor_char_position,
1679 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +00001680 max_return_elements,
1681 word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +00001682 matches);
1683 }
1684 }
1685
1686 return num_command_matches;
1687
1688}
1689
1690int
1691CommandInterpreter::HandleCompletion (const char *current_line,
1692 const char *cursor,
1693 const char *last_char,
1694 int match_start_point,
1695 int max_return_elements,
1696 StringList &matches)
1697{
1698 // We parse the argument up to the cursor, so the last argument in parsed_line is
1699 // the one containing the cursor, and the cursor is after the last character.
1700
1701 Args parsed_line(current_line, last_char - current_line);
1702 Args partial_parsed_line(current_line, cursor - current_line);
1703
Jim Ingham6247dbe2011-07-12 03:12:18 +00001704 // Don't complete comments, and if the line we are completing is just the history repeat character,
1705 // substitute the appropriate history line.
1706 const char *first_arg = parsed_line.GetArgumentAtIndex(0);
1707 if (first_arg)
1708 {
1709 if (first_arg[0] == m_comment_char)
1710 return 0;
1711 else if (first_arg[0] == m_repeat_char)
1712 {
1713 const char *history_string = FindHistoryString (first_arg);
1714 if (history_string != NULL)
1715 {
1716 matches.Clear();
1717 matches.InsertStringAtIndex(0, history_string);
1718 return -2;
1719 }
1720 else
1721 return 0;
1722
1723 }
1724 }
1725
1726
Chris Lattner24943d22010-06-08 16:52:24 +00001727 int num_args = partial_parsed_line.GetArgumentCount();
1728 int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
1729 int cursor_char_position;
1730
1731 if (cursor_index == -1)
1732 cursor_char_position = 0;
1733 else
1734 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
Jim Inghamcf037652010-12-14 19:56:01 +00001735
1736 if (cursor > current_line && cursor[-1] == ' ')
1737 {
1738 // We are just after a space. If we are in an argument, then we will continue
1739 // parsing, but if we are between arguments, then we have to complete whatever the next
1740 // element would be.
1741 // We can distinguish the two cases because if we are in an argument (e.g. because the space is
1742 // protected by a quote) then the space will also be in the parsed argument...
1743
1744 const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
1745 if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
1746 {
1747 parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '"');
1748 cursor_index++;
1749 cursor_char_position = 0;
1750 }
1751 }
Chris Lattner24943d22010-06-08 16:52:24 +00001752
1753 int num_command_matches;
1754
1755 matches.Clear();
1756
1757 // Only max_return_elements == -1 is supported at present:
1758 assert (max_return_elements == -1);
Jim Ingham802f8b02010-06-30 05:02:46 +00001759 bool word_complete;
Greg Clayton63094e02010-06-23 01:19:29 +00001760 num_command_matches = HandleCompletionMatches (parsed_line,
1761 cursor_index,
1762 cursor_char_position,
1763 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +00001764 max_return_elements,
1765 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +00001766 matches);
Chris Lattner24943d22010-06-08 16:52:24 +00001767
1768 if (num_command_matches <= 0)
1769 return num_command_matches;
1770
1771 if (num_args == 0)
1772 {
1773 // If we got an empty string, insert nothing.
1774 matches.InsertStringAtIndex(0, "");
1775 }
1776 else
1777 {
1778 // Now figure out if there is a common substring, and if so put that in element 0, otherwise
1779 // put an empty string in element 0.
1780 std::string command_partial_str;
1781 if (cursor_index >= 0)
Jim Inghame3663e82010-10-22 18:47:16 +00001782 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
1783 parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
Chris Lattner24943d22010-06-08 16:52:24 +00001784
1785 std::string common_prefix;
1786 matches.LongestCommonPrefix (common_prefix);
1787 int partial_name_len = command_partial_str.size();
1788
1789 // If we matched a unique single command, add a space...
Jim Ingham802f8b02010-06-30 05:02:46 +00001790 // Only do this if the completer told us this was a complete word, however...
1791 if (num_command_matches == 1 && word_complete)
Chris Lattner24943d22010-06-08 16:52:24 +00001792 {
1793 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
1794 if (quote_char != '\0')
1795 common_prefix.push_back(quote_char);
1796
1797 common_prefix.push_back(' ');
1798 }
1799 common_prefix.erase (0, partial_name_len);
1800 matches.InsertStringAtIndex(0, common_prefix.c_str());
1801 }
1802 return num_command_matches;
1803}
1804
Chris Lattner24943d22010-06-08 16:52:24 +00001805
1806CommandInterpreter::~CommandInterpreter ()
1807{
1808}
1809
1810const char *
1811CommandInterpreter::GetPrompt ()
1812{
Caroline Tice5bc8c972010-09-20 20:44:43 +00001813 return m_debugger.GetPrompt();
Chris Lattner24943d22010-06-08 16:52:24 +00001814}
1815
1816void
1817CommandInterpreter::SetPrompt (const char *new_prompt)
1818{
Caroline Tice5bc8c972010-09-20 20:44:43 +00001819 m_debugger.SetPrompt (new_prompt);
Chris Lattner24943d22010-06-08 16:52:24 +00001820}
1821
Jim Ingham5e16ef52010-10-04 19:49:29 +00001822size_t
Greg Clayton58928562011-02-09 01:08:52 +00001823CommandInterpreter::GetConfirmationInputReaderCallback
1824(
1825 void *baton,
1826 InputReader &reader,
1827 lldb::InputReaderAction action,
1828 const char *bytes,
1829 size_t bytes_len
1830)
Jim Ingham5e16ef52010-10-04 19:49:29 +00001831{
Greg Clayton58928562011-02-09 01:08:52 +00001832 File &out_file = reader.GetDebugger().GetOutputFile();
Jim Ingham5e16ef52010-10-04 19:49:29 +00001833 bool *response_ptr = (bool *) baton;
1834
1835 switch (action)
1836 {
1837 case eInputReaderActivate:
Greg Clayton58928562011-02-09 01:08:52 +00001838 if (out_file.IsValid())
Jim Ingham5e16ef52010-10-04 19:49:29 +00001839 {
1840 if (reader.GetPrompt())
Caroline Tice22a60092011-02-02 01:17:56 +00001841 {
Greg Clayton58928562011-02-09 01:08:52 +00001842 out_file.Printf ("%s", reader.GetPrompt());
1843 out_file.Flush ();
Caroline Tice22a60092011-02-02 01:17:56 +00001844 }
Jim Ingham5e16ef52010-10-04 19:49:29 +00001845 }
1846 break;
1847
1848 case eInputReaderDeactivate:
1849 break;
1850
1851 case eInputReaderReactivate:
Greg Clayton58928562011-02-09 01:08:52 +00001852 if (out_file.IsValid() && reader.GetPrompt())
Caroline Tice22a60092011-02-02 01:17:56 +00001853 {
Greg Clayton58928562011-02-09 01:08:52 +00001854 out_file.Printf ("%s", reader.GetPrompt());
1855 out_file.Flush ();
Caroline Tice22a60092011-02-02 01:17:56 +00001856 }
Jim Ingham5e16ef52010-10-04 19:49:29 +00001857 break;
Caroline Tice4a348082011-05-02 20:41:46 +00001858
1859 case eInputReaderAsynchronousOutputWritten:
1860 break;
1861
Jim Ingham5e16ef52010-10-04 19:49:29 +00001862 case eInputReaderGotToken:
1863 if (bytes_len == 0)
1864 {
1865 reader.SetIsDone(true);
1866 }
Jim Ingham36fe9912011-11-14 20:02:01 +00001867 else if (bytes[0] == 'y' || bytes[0] == 'Y')
Jim Ingham5e16ef52010-10-04 19:49:29 +00001868 {
1869 *response_ptr = true;
1870 reader.SetIsDone(true);
1871 }
Jim Ingham36fe9912011-11-14 20:02:01 +00001872 else if (bytes[0] == 'n' || bytes[0] == 'N')
Jim Ingham5e16ef52010-10-04 19:49:29 +00001873 {
1874 *response_ptr = false;
1875 reader.SetIsDone(true);
1876 }
1877 else
1878 {
Greg Clayton58928562011-02-09 01:08:52 +00001879 if (out_file.IsValid() && !reader.IsDone() && reader.GetPrompt())
Jim Ingham5e16ef52010-10-04 19:49:29 +00001880 {
Jim Ingham26183802011-11-17 01:22:00 +00001881 out_file.Printf ("Please answer \"y\" or \"n\".\n%s", reader.GetPrompt());
Greg Clayton58928562011-02-09 01:08:52 +00001882 out_file.Flush ();
Jim Ingham5e16ef52010-10-04 19:49:29 +00001883 }
1884 }
1885 break;
1886
Caroline Ticec4f55fe2010-11-19 20:47:54 +00001887 case eInputReaderInterrupt:
1888 case eInputReaderEndOfFile:
1889 *response_ptr = false; // Assume ^C or ^D means cancel the proposed action
1890 reader.SetIsDone (true);
1891 break;
1892
Jim Ingham5e16ef52010-10-04 19:49:29 +00001893 case eInputReaderDone:
1894 break;
1895 }
1896
1897 return bytes_len;
1898
1899}
1900
1901bool
1902CommandInterpreter::Confirm (const char *message, bool default_answer)
1903{
Jim Ingham93057472010-10-04 22:44:14 +00001904 // Check AutoConfirm first:
1905 if (m_debugger.GetAutoConfirm())
1906 return default_answer;
1907
Jim Ingham5e16ef52010-10-04 19:49:29 +00001908 InputReaderSP reader_sp (new InputReader(GetDebugger()));
1909 bool response = default_answer;
1910 if (reader_sp)
1911 {
1912 std::string prompt(message);
1913 prompt.append(": [");
1914 if (default_answer)
1915 prompt.append ("Y/n] ");
1916 else
1917 prompt.append ("y/N] ");
1918
1919 Error err (reader_sp->Initialize (CommandInterpreter::GetConfirmationInputReaderCallback,
1920 &response, // baton
1921 eInputReaderGranularityLine, // token size, to pass to callback function
1922 NULL, // end token
1923 prompt.c_str(), // prompt
1924 true)); // echo input
1925 if (err.Success())
1926 {
1927 GetDebugger().PushInputReader (reader_sp);
1928 }
1929 reader_sp->WaitOnReaderIsDone();
1930 }
1931 return response;
1932}
1933
1934
Chris Lattner24943d22010-06-08 16:52:24 +00001935void
1936CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
1937{
Jim Inghamd40f8a62010-07-06 22:46:59 +00001938 CommandObjectSP cmd_obj_sp = GetCommandSPExact (dest_cmd, true);
Chris Lattner24943d22010-06-08 16:52:24 +00001939
Sean Callananb386d822012-08-09 00:50:26 +00001940 if (cmd_obj_sp)
Chris Lattner24943d22010-06-08 16:52:24 +00001941 {
1942 CommandObject *cmd_obj = cmd_obj_sp.get();
1943 if (cmd_obj->IsCrossRefObject ())
1944 cmd_obj->AddObject (object_type);
1945 }
1946}
1947
Chris Lattner24943d22010-06-08 16:52:24 +00001948OptionArgVectorSP
1949CommandInterpreter::GetAliasOptions (const char *alias_name)
1950{
1951 OptionArgMap::iterator pos;
1952 OptionArgVectorSP ret_val;
1953
1954 std::string alias (alias_name);
1955
1956 if (HasAliasOptions())
1957 {
1958 pos = m_alias_options.find (alias);
1959 if (pos != m_alias_options.end())
1960 ret_val = pos->second;
1961 }
1962
1963 return ret_val;
1964}
1965
1966void
1967CommandInterpreter::RemoveAliasOptions (const char *alias_name)
1968{
1969 OptionArgMap::iterator pos = m_alias_options.find(alias_name);
1970 if (pos != m_alias_options.end())
1971 {
1972 m_alias_options.erase (pos);
1973 }
1974}
1975
1976void
1977CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
1978{
1979 m_alias_options[alias_name] = option_arg_vector_sp;
1980}
1981
1982bool
1983CommandInterpreter::HasCommands ()
1984{
1985 return (!m_command_dict.empty());
1986}
1987
1988bool
1989CommandInterpreter::HasAliases ()
1990{
1991 return (!m_alias_dict.empty());
1992}
1993
1994bool
1995CommandInterpreter::HasUserCommands ()
1996{
1997 return (!m_user_dict.empty());
1998}
1999
2000bool
2001CommandInterpreter::HasAliasOptions ()
2002{
2003 return (!m_alias_options.empty());
2004}
2005
Chris Lattner24943d22010-06-08 16:52:24 +00002006void
Caroline Ticebd5c63e2010-10-12 21:57:09 +00002007CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
2008 const char *alias_name,
2009 Args &cmd_args,
Caroline Tice44c841d2010-12-07 19:58:26 +00002010 std::string &raw_input_string,
Caroline Ticebd5c63e2010-10-12 21:57:09 +00002011 CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +00002012{
2013 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
Caroline Tice44c841d2010-12-07 19:58:26 +00002014
2015 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
Chris Lattner24943d22010-06-08 16:52:24 +00002016
Caroline Tice44c841d2010-12-07 19:58:26 +00002017 // Make sure that the alias name is the 0th element in cmd_args
2018 std::string alias_name_str = alias_name;
2019 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
2020 cmd_args.Unshift (alias_name);
2021
2022 Args new_args (alias_cmd_obj->GetCommandName());
2023 if (new_args.GetArgumentCount() == 2)
2024 new_args.Shift();
2025
Chris Lattner24943d22010-06-08 16:52:24 +00002026 if (option_arg_vector_sp.get())
2027 {
Caroline Tice44c841d2010-12-07 19:58:26 +00002028 if (wants_raw_input)
2029 {
2030 // We have a command that both has command options and takes raw input. Make *sure* it has a
2031 // " -- " in the right place in the raw_input_string.
2032 size_t pos = raw_input_string.find(" -- ");
2033 if (pos == std::string::npos)
2034 {
2035 // None found; assume it goes at the beginning of the raw input string
2036 raw_input_string.insert (0, " -- ");
2037 }
2038 }
Chris Lattner24943d22010-06-08 16:52:24 +00002039
2040 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
2041 int old_size = cmd_args.GetArgumentCount();
Caroline Ticebd5c63e2010-10-12 21:57:09 +00002042 std::vector<bool> used (old_size + 1, false);
2043
2044 used[0] = true;
Chris Lattner24943d22010-06-08 16:52:24 +00002045
2046 for (int i = 0; i < option_arg_vector->size(); ++i)
2047 {
2048 OptionArgPair option_pair = (*option_arg_vector)[i];
Caroline Tice44c841d2010-12-07 19:58:26 +00002049 OptionArgValue value_pair = option_pair.second;
2050 int value_type = value_pair.first;
Chris Lattner24943d22010-06-08 16:52:24 +00002051 std::string option = option_pair.first;
Caroline Tice44c841d2010-12-07 19:58:26 +00002052 std::string value = value_pair.second;
Chris Lattner24943d22010-06-08 16:52:24 +00002053 if (option.compare ("<argument>") == 0)
Caroline Tice44c841d2010-12-07 19:58:26 +00002054 {
2055 if (!wants_raw_input
2056 || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
2057 new_args.AppendArgument (value.c_str());
2058 }
Chris Lattner24943d22010-06-08 16:52:24 +00002059 else
2060 {
Caroline Tice44c841d2010-12-07 19:58:26 +00002061 if (value_type != optional_argument)
2062 new_args.AppendArgument (option.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00002063 if (value.compare ("<no-argument>") != 0)
2064 {
2065 int index = GetOptionArgumentPosition (value.c_str());
2066 if (index == 0)
Caroline Tice44c841d2010-12-07 19:58:26 +00002067 {
Chris Lattner24943d22010-06-08 16:52:24 +00002068 // value was NOT a positional argument; must be a real value
Caroline Tice44c841d2010-12-07 19:58:26 +00002069 if (value_type != optional_argument)
2070 new_args.AppendArgument (value.c_str());
2071 else
2072 {
2073 char buffer[255];
2074 ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
2075 new_args.AppendArgument (buffer);
2076 }
2077
2078 }
Chris Lattner24943d22010-06-08 16:52:24 +00002079 else if (index >= cmd_args.GetArgumentCount())
2080 {
2081 result.AppendErrorWithFormat
2082 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
2083 index);
2084 result.SetStatus (eReturnStatusFailed);
2085 return;
2086 }
2087 else
2088 {
Caroline Tice44c841d2010-12-07 19:58:26 +00002089 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2090 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
2091 if (strpos != std::string::npos)
2092 {
2093 raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
2094 }
2095
2096 if (value_type != optional_argument)
2097 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
2098 else
2099 {
2100 char buffer[255];
2101 ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
2102 cmd_args.GetArgumentAtIndex (index));
2103 new_args.AppendArgument (buffer);
2104 }
Caroline Ticebd5c63e2010-10-12 21:57:09 +00002105 used[index] = true;
Chris Lattner24943d22010-06-08 16:52:24 +00002106 }
2107 }
2108 }
2109 }
2110
2111 for (int j = 0; j < cmd_args.GetArgumentCount(); ++j)
2112 {
Caroline Tice44c841d2010-12-07 19:58:26 +00002113 if (!used[j] && !wants_raw_input)
Chris Lattner24943d22010-06-08 16:52:24 +00002114 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
2115 }
2116
2117 cmd_args.Clear();
2118 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2119 }
2120 else
2121 {
2122 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Caroline Tice44c841d2010-12-07 19:58:26 +00002123 // This alias was not created with any options; nothing further needs to be done, unless it is a command that
2124 // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
2125 // input string.
2126 if (wants_raw_input)
2127 {
2128 cmd_args.Clear();
2129 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2130 }
Chris Lattner24943d22010-06-08 16:52:24 +00002131 return;
2132 }
2133
2134 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2135 return;
2136}
2137
2138
2139int
2140CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
2141{
2142 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
2143 // of zero.
2144
2145 char *cptr = (char *) in_string;
2146
2147 // Does it start with '%'
2148 if (cptr[0] == '%')
2149 {
2150 ++cptr;
2151
2152 // Is the rest of it entirely digits?
2153 if (isdigit (cptr[0]))
2154 {
2155 const char *start = cptr;
2156 while (isdigit (cptr[0]))
2157 ++cptr;
2158
2159 // We've gotten to the end of the digits; are we at the end of the string?
2160 if (cptr[0] == '\0')
2161 position = atoi (start);
2162 }
2163 }
2164
2165 return position;
2166}
2167
2168void
2169CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
2170{
Jim Ingham574c3d62011-08-12 23:34:31 +00002171 FileSpec init_file;
Greg Claytond6edcb52011-09-11 00:01:44 +00002172 if (in_cwd)
Jim Ingham574c3d62011-08-12 23:34:31 +00002173 {
Greg Claytond6edcb52011-09-11 00:01:44 +00002174 // In the current working directory we don't load any program specific
2175 // .lldbinit files, we only look for a "./.lldbinit" file.
2176 if (m_skip_lldbinit_files)
2177 return;
2178
2179 init_file.SetFile ("./.lldbinit", true);
Jim Ingham574c3d62011-08-12 23:34:31 +00002180 }
Greg Claytond6edcb52011-09-11 00:01:44 +00002181 else
Jim Ingham574c3d62011-08-12 23:34:31 +00002182 {
Greg Claytond6edcb52011-09-11 00:01:44 +00002183 // If we aren't looking in the current working directory we are looking
2184 // in the home directory. We will first see if there is an application
2185 // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
2186 // "-" and the name of the program. If this file doesn't exist, we fall
2187 // back to just the "~/.lldbinit" file. We also obey any requests to not
2188 // load the init files.
2189 const char *init_file_path = "~/.lldbinit";
2190
2191 if (m_skip_app_init_files == false)
2192 {
2193 FileSpec program_file_spec (Host::GetProgramFileSpec());
2194 const char *program_name = program_file_spec.GetFilename().AsCString();
Jim Ingham574c3d62011-08-12 23:34:31 +00002195
Greg Claytond6edcb52011-09-11 00:01:44 +00002196 if (program_name)
2197 {
2198 char program_init_file_name[PATH_MAX];
2199 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name);
2200 init_file.SetFile (program_init_file_name, true);
2201 if (!init_file.Exists())
2202 init_file.Clear();
2203 }
2204 }
2205
2206 if (!init_file && !m_skip_lldbinit_files)
2207 init_file.SetFile (init_file_path, true);
2208 }
2209
Chris Lattner24943d22010-06-08 16:52:24 +00002210 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
2211 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
2212
2213 if (init_file.Exists())
2214 {
Jim Ingham949d5ac2011-02-18 00:54:25 +00002215 ExecutionContext *exe_ctx = NULL; // We don't have any context yet.
2216 bool stop_on_continue = true;
2217 bool stop_on_error = false;
2218 bool echo_commands = false;
2219 bool print_results = false;
2220
Enrico Granata01bc2d42012-05-31 01:09:06 +00002221 HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, eLazyBoolNo, result);
Chris Lattner24943d22010-06-08 16:52:24 +00002222 }
2223 else
2224 {
2225 // nothing to be done if the file doesn't exist
2226 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2227 }
2228}
2229
Greg Claytonb72d0f02011-04-12 05:54:46 +00002230PlatformSP
2231CommandInterpreter::GetPlatform (bool prefer_target_platform)
2232{
2233 PlatformSP platform_sp;
Greg Clayton567e7f32011-09-22 04:58:26 +00002234 if (prefer_target_platform)
2235 {
Greg Claytonbcaf99a2012-07-12 20:32:19 +00002236 ExecutionContext exe_ctx(GetExecutionContext());
2237 Target *target = exe_ctx.GetTargetPtr();
Greg Clayton567e7f32011-09-22 04:58:26 +00002238 if (target)
2239 platform_sp = target->GetPlatform();
2240 }
Greg Claytonb72d0f02011-04-12 05:54:46 +00002241
2242 if (!platform_sp)
2243 platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
2244 return platform_sp;
2245}
2246
Jim Ingham949d5ac2011-02-18 00:54:25 +00002247void
Jim Inghama4fede32011-03-11 01:51:49 +00002248CommandInterpreter::HandleCommands (const StringList &commands,
Jim Ingham949d5ac2011-02-18 00:54:25 +00002249 ExecutionContext *override_context,
2250 bool stop_on_continue,
2251 bool stop_on_error,
2252 bool echo_commands,
2253 bool print_results,
Enrico Granata01bc2d42012-05-31 01:09:06 +00002254 LazyBool add_to_history,
Jim Ingham949d5ac2011-02-18 00:54:25 +00002255 CommandReturnObject &result)
2256{
2257 size_t num_lines = commands.GetSize();
Jim Ingham949d5ac2011-02-18 00:54:25 +00002258
2259 // If we are going to continue past a "continue" then we need to run the commands synchronously.
2260 // Make sure you reset this value anywhere you return from the function.
2261
2262 bool old_async_execution = m_debugger.GetAsyncExecution();
2263
2264 // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
2265 // cause series of commands that change the context, then do an operation that relies on that context to fail.
2266
2267 if (override_context != NULL)
Greg Claytonb72d0f02011-04-12 05:54:46 +00002268 UpdateExecutionContext (override_context);
Jim Ingham949d5ac2011-02-18 00:54:25 +00002269
2270 if (!stop_on_continue)
2271 {
2272 m_debugger.SetAsyncExecution (false);
2273 }
2274
2275 for (int idx = 0; idx < num_lines; idx++)
2276 {
2277 const char *cmd = commands.GetStringAtIndex(idx);
2278 if (cmd[0] == '\0')
2279 continue;
2280
Jim Ingham949d5ac2011-02-18 00:54:25 +00002281 if (echo_commands)
2282 {
2283 result.AppendMessageWithFormat ("%s %s\n",
2284 GetPrompt(),
2285 cmd);
2286 }
2287
Greg Claytonaa378b12011-02-20 02:15:07 +00002288 CommandReturnObject tmp_result;
Johnny Chen8bdf57c2011-10-05 00:42:59 +00002289 // If override_context is not NULL, pass no_context_switching = true for
2290 // HandleCommand() since we updated our context already.
Enrico Granata01bc2d42012-05-31 01:09:06 +00002291 bool success = HandleCommand(cmd, add_to_history, tmp_result,
Johnny Chen8bdf57c2011-10-05 00:42:59 +00002292 NULL, /* override_context */
2293 true, /* repeat_on_empty_command */
2294 override_context != NULL /* no_context_switching */);
Jim Ingham949d5ac2011-02-18 00:54:25 +00002295
2296 if (print_results)
2297 {
2298 if (tmp_result.Succeeded())
Jim Ingham2e8cb8a2011-02-19 02:53:09 +00002299 result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
Jim Ingham949d5ac2011-02-18 00:54:25 +00002300 }
2301
2302 if (!success || !tmp_result.Succeeded())
2303 {
Jim Ingham862fd5c2012-04-24 02:25:07 +00002304 const char *error_msg = tmp_result.GetErrorData();
2305 if (error_msg == NULL || error_msg[0] == '\0')
2306 error_msg = "<unknown error>.\n";
Jim Ingham949d5ac2011-02-18 00:54:25 +00002307 if (stop_on_error)
2308 {
Jim Ingham862fd5c2012-04-24 02:25:07 +00002309 result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' failed with %s",
2310 idx, cmd, error_msg);
Jim Ingham949d5ac2011-02-18 00:54:25 +00002311 result.SetStatus (eReturnStatusFailed);
2312 m_debugger.SetAsyncExecution (old_async_execution);
2313 return;
2314 }
2315 else if (print_results)
2316 {
Jim Ingham862fd5c2012-04-24 02:25:07 +00002317 result.AppendMessageWithFormat ("Command #%d '%s' failed with %s",
Jim Ingham949d5ac2011-02-18 00:54:25 +00002318 idx + 1,
2319 cmd,
Jim Ingham862fd5c2012-04-24 02:25:07 +00002320 error_msg);
Jim Ingham949d5ac2011-02-18 00:54:25 +00002321 }
2322 }
2323
Caroline Tice4a348082011-05-02 20:41:46 +00002324 if (result.GetImmediateOutputStream())
2325 result.GetImmediateOutputStream()->Flush();
2326
2327 if (result.GetImmediateErrorStream())
2328 result.GetImmediateErrorStream()->Flush();
2329
Jim Ingham949d5ac2011-02-18 00:54:25 +00002330 // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
2331 // could be running (for instance in Breakpoint Commands.
2332 // So we check the return value to see if it is has running in it.
2333 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
2334 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
2335 {
2336 if (stop_on_continue)
2337 {
2338 // If we caused the target to proceed, and we're going to stop in that case, set the
2339 // status in our real result before returning. This is an error if the continue was not the
2340 // last command in the set of commands to be run.
2341 if (idx != num_lines - 1)
2342 result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' continued the target.\n",
2343 idx + 1, cmd);
2344 else
2345 result.AppendMessageWithFormat ("Command #%d '%s' continued the target.\n", idx + 1, cmd);
2346
2347 result.SetStatus(tmp_result.GetStatus());
2348 m_debugger.SetAsyncExecution (old_async_execution);
2349
2350 return;
2351 }
2352 }
2353
2354 }
2355
2356 result.SetStatus (eReturnStatusSuccessFinishResult);
2357 m_debugger.SetAsyncExecution (old_async_execution);
2358
2359 return;
2360}
2361
2362void
2363CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
2364 ExecutionContext *context,
2365 bool stop_on_continue,
2366 bool stop_on_error,
2367 bool echo_command,
2368 bool print_result,
Enrico Granata01bc2d42012-05-31 01:09:06 +00002369 LazyBool add_to_history,
Jim Ingham949d5ac2011-02-18 00:54:25 +00002370 CommandReturnObject &result)
2371{
2372 if (cmd_file.Exists())
2373 {
2374 bool success;
2375 StringList commands;
2376 success = commands.ReadFileLines(cmd_file);
2377 if (!success)
2378 {
2379 result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString());
2380 result.SetStatus (eReturnStatusFailed);
2381 return;
2382 }
Enrico Granata01bc2d42012-05-31 01:09:06 +00002383 m_command_source_depth++;
2384 HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, add_to_history, result);
2385 m_command_source_depth--;
Jim Ingham949d5ac2011-02-18 00:54:25 +00002386 }
2387 else
2388 {
2389 result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
2390 cmd_file.GetFilename().AsCString());
2391 result.SetStatus (eReturnStatusFailed);
2392 return;
2393 }
2394}
2395
Chris Lattner24943d22010-06-08 16:52:24 +00002396ScriptInterpreter *
2397CommandInterpreter::GetScriptInterpreter ()
2398{
Enrico Granatac5c10a42012-07-10 18:23:48 +00002399 // <rdar://problem/11751427>
2400 // we need to protect the initialization of the script interpreter
2401 // otherwise we could end up with two threads both trying to create
2402 // their instance of it, and for some languages (e.g. Python)
2403 // this is a bulletproof recipe for disaster!
2404 // this needs to be a function-level static because multiple Debugger instances living in the same process
2405 // still need to be isolated and not try to initialize Python concurrently
Enrico Granatab88c0a92012-07-10 19:04:14 +00002406 static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
2407 Mutex::Locker interpreter_lock(g_interpreter_mutex);
Enrico Granatac5c10a42012-07-10 18:23:48 +00002408
Caroline Tice0aa2e552011-01-14 00:29:16 +00002409 if (m_script_interpreter_ap.get() != NULL)
2410 return m_script_interpreter_ap.get();
Greg Clayton63094e02010-06-23 01:19:29 +00002411
Caroline Tice0aa2e552011-01-14 00:29:16 +00002412 lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
2413 switch (script_lang)
Chris Lattner24943d22010-06-08 16:52:24 +00002414 {
Greg Clayton3e4238d2011-11-04 03:34:56 +00002415 case eScriptLanguagePython:
2416#ifndef LLDB_DISABLE_PYTHON
2417 m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
2418 break;
2419#else
2420 // Fall through to the None case when python is disabled
2421#endif
Caroline Tice0aa2e552011-01-14 00:29:16 +00002422 case eScriptLanguageNone:
2423 m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
2424 break;
Caroline Tice0aa2e552011-01-14 00:29:16 +00002425 default:
2426 break;
2427 };
2428
2429 return m_script_interpreter_ap.get();
Chris Lattner24943d22010-06-08 16:52:24 +00002430}
2431
2432
2433
2434bool
2435CommandInterpreter::GetSynchronous ()
2436{
2437 return m_synchronous_execution;
2438}
2439
2440void
2441CommandInterpreter::SetSynchronous (bool value)
2442{
Johnny Chend7a4eb02010-10-14 01:22:03 +00002443 m_synchronous_execution = value;
Chris Lattner24943d22010-06-08 16:52:24 +00002444}
2445
2446void
2447CommandInterpreter::OutputFormattedHelpText (Stream &strm,
2448 const char *word_text,
2449 const char *separator,
2450 const char *help_text,
2451 uint32_t max_word_len)
2452{
Greg Clayton238c0a12010-09-18 01:14:36 +00002453 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2454
Chris Lattner24943d22010-06-08 16:52:24 +00002455 int indent_size = max_word_len + strlen (separator) + 2;
2456
2457 strm.IndentMore (indent_size);
Greg Claytond284b662011-02-18 01:44:25 +00002458
2459 StreamString text_strm;
2460 text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
2461
2462 size_t len = text_strm.GetSize();
2463 const char *text = text_strm.GetData();
Chris Lattner24943d22010-06-08 16:52:24 +00002464 if (text[len - 1] == '\n')
Greg Claytond284b662011-02-18 01:44:25 +00002465 {
2466 text_strm.EOL();
2467 len = text_strm.GetSize();
2468 }
Chris Lattner24943d22010-06-08 16:52:24 +00002469
2470 if (len < max_columns)
2471 {
2472 // Output it as a single line.
2473 strm.Printf ("%s", text);
2474 }
2475 else
2476 {
2477 // We need to break it up into multiple lines.
2478 bool first_line = true;
2479 int text_width;
2480 int start = 0;
2481 int end = start;
2482 int final_end = strlen (text);
2483 int sub_len;
2484
2485 while (end < final_end)
2486 {
2487 if (first_line)
2488 text_width = max_columns - 1;
2489 else
2490 text_width = max_columns - indent_size - 1;
2491
2492 // Don't start the 'text' on a space, since we're already outputting the indentation.
2493 if (!first_line)
2494 {
2495 while ((start < final_end) && (text[start] == ' '))
2496 start++;
2497 }
2498
2499 end = start + text_width;
2500 if (end > final_end)
2501 end = final_end;
2502 else
2503 {
2504 // If we're not at the end of the text, make sure we break the line on white space.
2505 while (end > start
2506 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
2507 end--;
2508 }
2509
2510 sub_len = end - start;
2511 if (start != 0)
2512 strm.EOL();
2513 if (!first_line)
2514 strm.Indent();
2515 else
2516 first_line = false;
2517 assert (start <= final_end);
2518 assert (start + sub_len <= final_end);
2519 if (sub_len > 0)
2520 strm.Write (text + start, sub_len);
2521 start = end + 1;
2522 }
2523 }
2524 strm.EOL();
2525 strm.IndentLess(indent_size);
Chris Lattner24943d22010-06-08 16:52:24 +00002526}
2527
2528void
Enrico Granata1bba6e52011-07-07 00:38:40 +00002529CommandInterpreter::OutputHelpText (Stream &strm,
2530 const char *word_text,
2531 const char *separator,
2532 const char *help_text,
2533 uint32_t max_word_len)
2534{
2535 int indent_size = max_word_len + strlen (separator) + 2;
2536
2537 strm.IndentMore (indent_size);
2538
2539 StreamString text_strm;
2540 text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
2541
2542 const uint32_t max_columns = m_debugger.GetTerminalWidth();
Enrico Granata1bba6e52011-07-07 00:38:40 +00002543
2544 size_t len = text_strm.GetSize();
2545 const char *text = text_strm.GetData();
2546
2547 uint32_t chars_left = max_columns;
2548
2549 for (uint32_t i = 0; i < len; i++)
2550 {
2551 if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
2552 {
Enrico Granata1bba6e52011-07-07 00:38:40 +00002553 chars_left = max_columns - indent_size;
2554 strm.EOL();
2555 strm.Indent();
2556 }
2557 else
2558 {
2559 strm.PutChar(text[i]);
2560 chars_left--;
2561 }
2562
2563 }
2564
2565 strm.EOL();
2566 strm.IndentLess(indent_size);
2567}
2568
2569void
Chris Lattner24943d22010-06-08 16:52:24 +00002570CommandInterpreter::AproposAllSubCommands (CommandObject *cmd_obj, const char *prefix, const char *search_word,
2571 StringList &commands_found, StringList &commands_help)
2572{
2573 CommandObject::CommandMap::const_iterator pos;
2574 CommandObject::CommandMap sub_cmd_dict = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict;
2575 CommandObject *sub_cmd_obj;
2576
2577 for (pos = sub_cmd_dict.begin(); pos != sub_cmd_dict.end(); ++pos)
2578 {
2579 const char * command_name = pos->first.c_str();
2580 sub_cmd_obj = pos->second.get();
2581 StreamString complete_command_name;
2582
2583 complete_command_name.Printf ("%s %s", prefix, command_name);
2584
Greg Clayton238c0a12010-09-18 01:14:36 +00002585 if (sub_cmd_obj->HelpTextContainsWord (search_word))
Chris Lattner24943d22010-06-08 16:52:24 +00002586 {
2587 commands_found.AppendString (complete_command_name.GetData());
2588 commands_help.AppendString (sub_cmd_obj->GetHelp());
2589 }
2590
2591 if (sub_cmd_obj->IsMultiwordObject())
2592 AproposAllSubCommands (sub_cmd_obj, complete_command_name.GetData(), search_word, commands_found,
2593 commands_help);
2594 }
2595
2596}
2597
2598void
2599CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
2600 StringList &commands_help)
2601{
2602 CommandObject::CommandMap::const_iterator pos;
2603
2604 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
2605 {
2606 const char *command_name = pos->first.c_str();
2607 CommandObject *cmd_obj = pos->second.get();
2608
Greg Clayton238c0a12010-09-18 01:14:36 +00002609 if (cmd_obj->HelpTextContainsWord (search_word))
Chris Lattner24943d22010-06-08 16:52:24 +00002610 {
2611 commands_found.AppendString (command_name);
2612 commands_help.AppendString (cmd_obj->GetHelp());
2613 }
2614
2615 if (cmd_obj->IsMultiwordObject())
2616 AproposAllSubCommands (cmd_obj, command_name, search_word, commands_found, commands_help);
2617
2618 }
2619}
Greg Claytonb72d0f02011-04-12 05:54:46 +00002620
2621
2622void
2623CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
2624{
Greg Claytonb72d0f02011-04-12 05:54:46 +00002625 if (override_context != NULL)
2626 {
Greg Claytonbcaf99a2012-07-12 20:32:19 +00002627 m_exe_ctx_ref = *override_context;
Greg Claytonb72d0f02011-04-12 05:54:46 +00002628 }
2629 else
2630 {
Greg Claytonbcaf99a2012-07-12 20:32:19 +00002631 const bool adopt_selected = true;
2632 m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
Greg Claytonb72d0f02011-04-12 05:54:46 +00002633 }
2634}
2635
Jim Ingham6247dbe2011-07-12 03:12:18 +00002636void
2637CommandInterpreter::DumpHistory (Stream &stream, uint32_t count) const
2638{
2639 DumpHistory (stream, 0, count - 1);
2640}
2641
2642void
2643CommandInterpreter::DumpHistory (Stream &stream, uint32_t start, uint32_t end) const
2644{
Greg Clayton7268b4c2011-10-28 21:38:01 +00002645 const size_t last_idx = std::min<size_t>(m_command_history.size(), end + 1);
2646 for (size_t i = start; i < last_idx; i++)
Jim Ingham6247dbe2011-07-12 03:12:18 +00002647 {
2648 if (!m_command_history[i].empty())
2649 {
2650 stream.Indent();
Greg Clayton7268b4c2011-10-28 21:38:01 +00002651 stream.Printf ("%4zu: %s\n", i, m_command_history[i].c_str());
Jim Ingham6247dbe2011-07-12 03:12:18 +00002652 }
2653 }
2654}
2655
2656const char *
2657CommandInterpreter::FindHistoryString (const char *input_str) const
2658{
2659 if (input_str[0] != m_repeat_char)
2660 return NULL;
2661 if (input_str[1] == '-')
2662 {
2663 bool success;
2664 uint32_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success);
2665 if (!success)
2666 return NULL;
2667 if (idx > m_command_history.size())
2668 return NULL;
2669 idx = m_command_history.size() - idx;
2670 return m_command_history[idx].c_str();
2671
2672 }
2673 else if (input_str[1] == m_repeat_char)
2674 {
2675 if (m_command_history.empty())
2676 return NULL;
2677 else
2678 return m_command_history.back().c_str();
2679 }
2680 else
2681 {
2682 bool success;
2683 uint32_t idx = Args::StringToUInt32 (input_str+1, 0, 0, &success);
2684 if (!success)
2685 return NULL;
2686 if (idx >= m_command_history.size())
2687 return NULL;
2688 return m_command_history[idx].c_str();
2689 }
2690}