blob: 929fbfb29c4eb508db5050425564b88742f08637 [file] [log] [blame]
Chris Lattner30fdc8d2010-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
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012#include <string>
Caroline Tice4ab31c92010-10-12 21:57:09 +000013#include <vector>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014#include <stdlib.h>
15
Greg Clayton4a33d312011-06-23 17:59:56 +000016#include "CommandObjectScript.h"
Peter Collingbourne08405b62011-06-23 20:37:26 +000017#include "lldb/Interpreter/CommandObjectRegexCommand.h"
Greg Clayton4a33d312011-06-23 17:59:56 +000018
Eli Friedman3afb70c2010-06-13 02:17:17 +000019#include "../Commands/CommandObjectApropos.h"
20#include "../Commands/CommandObjectArgs.h"
21#include "../Commands/CommandObjectBreakpoint.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000022#include "../Commands/CommandObjectDisassemble.h"
23#include "../Commands/CommandObjectExpression.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000024#include "../Commands/CommandObjectFrame.h"
Greg Clayton44d93782014-01-27 23:43:24 +000025#include "../Commands/CommandObjectGUI.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000026#include "../Commands/CommandObjectHelp.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000027#include "../Commands/CommandObjectLog.h"
28#include "../Commands/CommandObjectMemory.h"
Greg Claytonded470d2011-03-19 01:12:21 +000029#include "../Commands/CommandObjectPlatform.h"
Enrico Granata21dfcd92012-09-28 23:57:51 +000030#include "../Commands/CommandObjectPlugin.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000031#include "../Commands/CommandObjectProcess.h"
32#include "../Commands/CommandObjectQuit.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000033#include "../Commands/CommandObjectRegister.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000034#include "../Commands/CommandObjectSettings.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000035#include "../Commands/CommandObjectSource.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000036#include "../Commands/CommandObjectCommands.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000037#include "../Commands/CommandObjectSyntax.h"
38#include "../Commands/CommandObjectTarget.h"
39#include "../Commands/CommandObjectThread.h"
Greg Clayton4a33d312011-06-23 17:59:56 +000040#include "../Commands/CommandObjectType.h"
Johnny Chen31c39da2010-12-23 20:21:44 +000041#include "../Commands/CommandObjectVersion.h"
Johnny Chenf04ee932011-09-22 18:04:58 +000042#include "../Commands/CommandObjectWatchpoint.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043
Greg Clayton7d2ef162013-03-29 17:03:23 +000044
Chris Lattner30fdc8d2010-06-08 16:52:24 +000045#include "lldb/Core/Debugger.h"
Enrico Granatab5887262012-10-29 21:18:03 +000046#include "lldb/Core/Log.h"
Greg Claytonf0066ad2014-05-02 00:45:31 +000047#include "lldb/Core/State.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048#include "lldb/Core/Stream.h"
Greg Clayton44d93782014-01-27 23:43:24 +000049#include "lldb/Core/StreamFile.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000050#include "lldb/Core/Timer.h"
Enrico Granatab5887262012-10-29 21:18:03 +000051
Greg Clayton44d93782014-01-27 23:43:24 +000052#include "lldb/Host/Editline.h"
Greg Clayton7fb56d02011-02-01 01:31:41 +000053#include "lldb/Host/Host.h"
Enrico Granatab5887262012-10-29 21:18:03 +000054
55#include "lldb/Interpreter/Args.h"
Greg Clayton7d2ef162013-03-29 17:03:23 +000056#include "lldb/Interpreter/CommandCompletions.h"
Enrico Granatab5887262012-10-29 21:18:03 +000057#include "lldb/Interpreter/CommandInterpreter.h"
Greg Clayton7d2ef162013-03-29 17:03:23 +000058#include "lldb/Interpreter/CommandReturnObject.h"
Enrico Granatab5887262012-10-29 21:18:03 +000059#include "lldb/Interpreter/Options.h"
60#include "lldb/Interpreter/ScriptInterpreterNone.h"
61#include "lldb/Interpreter/ScriptInterpreterPython.h"
62
63
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064#include "lldb/Target/Process.h"
65#include "lldb/Target/Thread.h"
66#include "lldb/Target/TargetList.h"
67
Enrico Granatab5887262012-10-29 21:18:03 +000068#include "lldb/Utility/CleanUp.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000069
70using namespace lldb;
71using namespace lldb_private;
72
Greg Clayton754a9362012-08-23 00:22:02 +000073
74static PropertyDefinition
75g_properties[] =
76{
Ed Masted78c9572014-04-20 00:31:37 +000077 { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." },
78 { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." },
79 { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." },
80 { nullptr , OptionValue::eTypeInvalid, true, 0 , nullptr, nullptr, nullptr }
Greg Clayton754a9362012-08-23 00:22:02 +000081};
82
83enum
84{
Enrico Granatabcba2b22013-01-17 21:36:19 +000085 ePropertyExpandRegexAliases = 0,
Enrico Granata012d4fc2013-06-11 01:26:35 +000086 ePropertyPromptOnQuit = 1,
87 ePropertyStopCmdSourceOnError = 2
Greg Clayton754a9362012-08-23 00:22:02 +000088};
89
Jim Ingham4bddaeb2012-02-16 06:50:00 +000090ConstString &
91CommandInterpreter::GetStaticBroadcasterClass ()
92{
93 static ConstString class_name ("lldb.commandInterpreter");
94 return class_name;
95}
96
Chris Lattner30fdc8d2010-06-08 16:52:24 +000097CommandInterpreter::CommandInterpreter
98(
Greg Clayton66111032010-06-23 01:19:29 +000099 Debugger &debugger,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100 ScriptLanguage script_language,
Greg Clayton66111032010-06-23 01:19:29 +0000101 bool synchronous_execution
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000102) :
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000103 Broadcaster (&debugger, "lldb.command-interpreter"),
Greg Clayton754a9362012-08-23 00:22:02 +0000104 Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
Greg Clayton44d93782014-01-27 23:43:24 +0000105 IOHandlerDelegate (IOHandlerDelegate::Completion::LLDBCommand),
Greg Clayton66111032010-06-23 01:19:29 +0000106 m_debugger (debugger),
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000107 m_synchronous_execution (synchronous_execution),
Caroline Tice2f88aad2011-01-14 00:29:16 +0000108 m_skip_lldbinit_files (false),
Jim Ingham16e0c682011-08-12 23:34:31 +0000109 m_skip_app_init_files (false),
Jim Inghame16c50a2011-02-18 00:54:25 +0000110 m_script_interpreter_ap (),
Greg Clayton44d93782014-01-27 23:43:24 +0000111 m_command_io_handler_sp (),
Caroline Ticed61c10b2011-06-16 16:27:19 +0000112 m_comment_char ('#'),
Johnny Chen4ac1d9e2012-08-09 22:06:10 +0000113 m_batch_command_mode (false),
Enrico Granata5f5ab602012-05-31 01:09:06 +0000114 m_truncation_warning(eNoTruncation),
115 m_command_source_depth (0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116{
Greg Clayton67cc0632012-08-22 17:17:09 +0000117 debugger.SetScriptLanguage (script_language);
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000118 SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
119 SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
Greg Clayton67cc0632012-08-22 17:17:09 +0000120 SetEventName (eBroadcastBitQuitCommandReceived, "quit");
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000121 CheckInWithManager ();
Greg Clayton754a9362012-08-23 00:22:02 +0000122 m_collection_sp->Initialize (g_properties);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000123}
124
Greg Clayton754a9362012-08-23 00:22:02 +0000125bool
126CommandInterpreter::GetExpandRegexAliases () const
127{
128 const uint32_t idx = ePropertyExpandRegexAliases;
Ed Masted78c9572014-04-20 00:31:37 +0000129 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
Greg Clayton754a9362012-08-23 00:22:02 +0000130}
131
Enrico Granatabcba2b22013-01-17 21:36:19 +0000132bool
133CommandInterpreter::GetPromptOnQuit () const
134{
135 const uint32_t idx = ePropertyPromptOnQuit;
Ed Masted78c9572014-04-20 00:31:37 +0000136 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
Enrico Granatabcba2b22013-01-17 21:36:19 +0000137}
Greg Clayton754a9362012-08-23 00:22:02 +0000138
Enrico Granata012d4fc2013-06-11 01:26:35 +0000139bool
140CommandInterpreter::GetStopCmdSourceOnError () const
141{
142 const uint32_t idx = ePropertyStopCmdSourceOnError;
Ed Masted78c9572014-04-20 00:31:37 +0000143 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
Enrico Granata012d4fc2013-06-11 01:26:35 +0000144}
145
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000146void
147CommandInterpreter::Initialize ()
148{
149 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
150
151 CommandReturnObject result;
152
153 LoadCommandDictionary ();
154
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000155 // Set up some initial aliases.
Caroline Ticeca90c472011-05-06 21:37:15 +0000156 CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
157 if (cmd_obj_sp)
158 {
159 AddAlias ("q", cmd_obj_sp);
160 AddAlias ("exit", cmd_obj_sp);
161 }
Sean Callanan247e62a2012-05-04 23:15:02 +0000162
Johnny Chen6d675242012-08-24 18:15:45 +0000163 cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
Sean Callanan247e62a2012-05-04 23:15:02 +0000164 if (cmd_obj_sp)
165 {
166 AddAlias ("attach", cmd_obj_sp);
167 }
Caroline Ticeca90c472011-05-06 21:37:15 +0000168
Johnny Chen6d675242012-08-24 18:15:45 +0000169 cmd_obj_sp = GetCommandSPExact ("process detach",false);
170 if (cmd_obj_sp)
171 {
172 AddAlias ("detach", cmd_obj_sp);
173 }
174
Caroline Ticeca90c472011-05-06 21:37:15 +0000175 cmd_obj_sp = GetCommandSPExact ("process continue", false);
176 if (cmd_obj_sp)
177 {
178 AddAlias ("c", cmd_obj_sp);
179 AddAlias ("continue", cmd_obj_sp);
180 }
181
182 cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
183 if (cmd_obj_sp)
184 AddAlias ("b", cmd_obj_sp);
185
Jim Inghamca36cd12012-10-05 19:16:31 +0000186 cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
187 if (cmd_obj_sp)
188 AddAlias ("tbreak", cmd_obj_sp);
189
Caroline Ticeca90c472011-05-06 21:37:15 +0000190 cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
191 if (cmd_obj_sp)
Jason Molendaf385f122011-10-22 00:47:41 +0000192 {
193 AddAlias ("stepi", cmd_obj_sp);
Caroline Ticeca90c472011-05-06 21:37:15 +0000194 AddAlias ("si", cmd_obj_sp);
Jason Molendaf385f122011-10-22 00:47:41 +0000195 }
196
197 cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false);
198 if (cmd_obj_sp)
199 {
200 AddAlias ("nexti", cmd_obj_sp);
201 AddAlias ("ni", cmd_obj_sp);
202 }
Caroline Ticeca90c472011-05-06 21:37:15 +0000203
204 cmd_obj_sp = GetCommandSPExact ("thread step-in", false);
205 if (cmd_obj_sp)
206 {
207 AddAlias ("s", cmd_obj_sp);
208 AddAlias ("step", cmd_obj_sp);
209 }
210
211 cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
212 if (cmd_obj_sp)
213 {
214 AddAlias ("n", cmd_obj_sp);
215 AddAlias ("next", cmd_obj_sp);
216 }
217
218 cmd_obj_sp = GetCommandSPExact ("thread step-out", false);
219 if (cmd_obj_sp)
220 {
Caroline Ticeca90c472011-05-06 21:37:15 +0000221 AddAlias ("finish", cmd_obj_sp);
222 }
223
Jim Ingham6d6d1072011-12-02 01:12:59 +0000224 cmd_obj_sp = GetCommandSPExact ("frame select", false);
225 if (cmd_obj_sp)
226 {
227 AddAlias ("f", cmd_obj_sp);
228 }
229
Jim Inghamca36cd12012-10-05 19:16:31 +0000230 cmd_obj_sp = GetCommandSPExact ("thread select", false);
231 if (cmd_obj_sp)
232 {
233 AddAlias ("t", cmd_obj_sp);
234 }
235
Richard Mittonf86248d2013-09-12 02:20:34 +0000236 cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false);
237 if (cmd_obj_sp)
238 {
239 AddAlias ("j", cmd_obj_sp);
240 AddAlias ("jump", cmd_obj_sp);
241 }
242
Greg Clayton6bade322013-02-01 23:33:03 +0000243 cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
Caroline Ticeca90c472011-05-06 21:37:15 +0000244 if (cmd_obj_sp)
245 {
246 AddAlias ("l", cmd_obj_sp);
247 AddAlias ("list", cmd_obj_sp);
248 }
249
Greg Claytonef5651d2013-02-12 18:52:24 +0000250 cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
251 if (cmd_obj_sp)
252 {
253 AddAlias ("env", cmd_obj_sp);
254 }
255
Caroline Ticeca90c472011-05-06 21:37:15 +0000256 cmd_obj_sp = GetCommandSPExact ("memory read", false);
257 if (cmd_obj_sp)
258 AddAlias ("x", cmd_obj_sp);
259
260 cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
261 if (cmd_obj_sp)
262 AddAlias ("up", cmd_obj_sp);
263
264 cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
265 if (cmd_obj_sp)
266 AddAlias ("down", cmd_obj_sp);
267
Jason Molenda0c8e0062011-10-25 02:11:20 +0000268 cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
Jason Molendabc7748b2011-10-22 01:30:52 +0000269 if (cmd_obj_sp)
270 AddAlias ("display", cmd_obj_sp);
Jim Ingham7e18e422011-10-24 18:37:00 +0000271
272 cmd_obj_sp = GetCommandSPExact ("disassemble", false);
273 if (cmd_obj_sp)
274 AddAlias ("dis", cmd_obj_sp);
275
276 cmd_obj_sp = GetCommandSPExact ("disassemble", false);
277 if (cmd_obj_sp)
278 AddAlias ("di", cmd_obj_sp);
279
280
Jason Molendabc7748b2011-10-22 01:30:52 +0000281
Jason Molenda0c8e0062011-10-25 02:11:20 +0000282 cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
Jason Molendabc7748b2011-10-22 01:30:52 +0000283 if (cmd_obj_sp)
284 AddAlias ("undisplay", cmd_obj_sp);
285
Jim Ingham71bf2992012-10-10 16:51:31 +0000286 cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
287 if (cmd_obj_sp)
288 AddAlias ("bt", cmd_obj_sp);
289
Caroline Ticeca90c472011-05-06 21:37:15 +0000290 cmd_obj_sp = GetCommandSPExact ("target create", false);
291 if (cmd_obj_sp)
292 AddAlias ("file", cmd_obj_sp);
293
294 cmd_obj_sp = GetCommandSPExact ("target modules", false);
295 if (cmd_obj_sp)
296 AddAlias ("image", cmd_obj_sp);
297
298
299 OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
Jim Inghamffba2292011-03-22 02:29:32 +0000300
Caroline Ticeca90c472011-05-06 21:37:15 +0000301 cmd_obj_sp = GetCommandSPExact ("expression", false);
302 if (cmd_obj_sp)
Sean Callanan90e579f2013-04-17 17:23:58 +0000303 {
Caroline Ticeca90c472011-05-06 21:37:15 +0000304 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
305 AddAlias ("p", cmd_obj_sp);
306 AddAlias ("print", cmd_obj_sp);
Sean Callanan316d5e42012-08-08 01:30:34 +0000307 AddAlias ("call", cmd_obj_sp);
Caroline Ticeca90c472011-05-06 21:37:15 +0000308 AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp);
309 AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp);
Sean Callanan316d5e42012-08-08 01:30:34 +0000310 AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp);
Caroline Ticeca90c472011-05-06 21:37:15 +0000311
312 alias_arguments_vector_sp.reset (new OptionArgVector);
Greg Clayton9e57dcd2013-05-15 01:03:08 +0000313 ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp);
Caroline Ticeca90c472011-05-06 21:37:15 +0000314 AddAlias ("po", cmd_obj_sp);
315 AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
316 }
317
Sean Callanan2e1d9ba2012-06-01 23:29:32 +0000318 cmd_obj_sp = GetCommandSPExact ("process kill", false);
319 if (cmd_obj_sp)
Greg Claytone86fd742012-09-27 00:02:27 +0000320 {
Sean Callanan2e1d9ba2012-06-01 23:29:32 +0000321 AddAlias ("kill", cmd_obj_sp);
Greg Claytone86fd742012-09-27 00:02:27 +0000322 }
Sean Callanan2e1d9ba2012-06-01 23:29:32 +0000323
Caroline Ticeca90c472011-05-06 21:37:15 +0000324 cmd_obj_sp = GetCommandSPExact ("process launch", false);
325 if (cmd_obj_sp)
326 {
327 alias_arguments_vector_sp.reset (new OptionArgVector);
Jason Molendaa3329782014-03-29 18:54:20 +0000328#if defined (__arm__) || defined (__arm64__)
Jason Molenda85da3122012-07-06 02:46:23 +0000329 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
330#else
Ed Maste7c566672013-09-05 21:38:45 +0000331 ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=" LLDB_DEFAULT_SHELL " --", alias_arguments_vector_sp);
Jason Molenda85da3122012-07-06 02:46:23 +0000332#endif
Caroline Ticeca90c472011-05-06 21:37:15 +0000333 AddAlias ("r", cmd_obj_sp);
334 AddAlias ("run", cmd_obj_sp);
335 AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp);
336 AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp);
337 }
Greg Clayton843d62d2012-03-29 21:47:51 +0000338
339 cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
340 if (cmd_obj_sp)
341 {
342 AddAlias ("add-dsym", cmd_obj_sp);
343 }
Sean Callananfc732752012-05-21 18:25:19 +0000344
345 cmd_obj_sp = GetCommandSPExact ("breakpoint set", false);
346 if (cmd_obj_sp)
347 {
348 alias_arguments_vector_sp.reset (new OptionArgVector);
349 ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp);
Jim Ingham06d282d2012-10-18 23:24:12 +0000350 AddAlias ("rbreak", cmd_obj_sp);
351 AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp);
Sean Callananfc732752012-05-21 18:25:19 +0000352 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000353}
354
Greg Clayton0c4129f2014-04-25 00:35:14 +0000355void
356CommandInterpreter::Clear()
357{
358 m_command_io_handler_sp.reset();
Greg Claytoned6499f2014-04-25 23:55:12 +0000359
360 if (m_script_interpreter_ap)
361 m_script_interpreter_ap->Clear();
Greg Clayton0c4129f2014-04-25 00:35:14 +0000362}
363
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000364const char *
365CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
366{
367 // This function has not yet been implemented.
368
369 // Look for any embedded script command
370 // If found,
371 // get interpreter object from the command dictionary,
372 // call execute_one_command on it,
373 // get the results as a string,
374 // substitute that string for current stuff.
375
376 return arg;
377}
378
379
380void
381CommandInterpreter::LoadCommandDictionary ()
382{
383 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
384
Caroline Ticedaccaa92010-09-20 20:44:43 +0000385 lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000386
Greg Claytona7015092010-09-18 01:14:36 +0000387 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000388 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
Johnny Chenb89982d2011-04-21 00:39:18 +0000389 m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
Greg Claytona7015092010-09-18 01:14:36 +0000390 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
391 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000392 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
Greg Clayton44d93782014-01-27 23:43:24 +0000393 m_command_dict["gui"] = CommandObjectSP (new CommandObjectGUI (*this));
Greg Claytona7015092010-09-18 01:14:36 +0000394 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000395 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this));
396 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this));
Greg Claytonded470d2011-03-19 01:12:21 +0000397 m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this));
Enrico Granata21dfcd92012-09-28 23:57:51 +0000398 m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000399 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
Greg Claytona7015092010-09-18 01:14:36 +0000400 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000401 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this));
Greg Claytona7015092010-09-18 01:14:36 +0000402 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language));
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000403 m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
Jim Inghamebc09c32010-07-07 03:36:20 +0000404 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000405 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
406 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this));
Enrico Granata223383e2011-08-16 23:24:13 +0000407 m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this));
Johnny Chen31c39da2010-12-23 20:21:44 +0000408 m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this));
Johnny Chenf04ee932011-09-22 18:04:58 +0000409 m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000410
Jim Inghamca36cd12012-10-05 19:16:31 +0000411 const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
412 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
Greg Clayton722e8852013-02-08 02:54:24 +0000413 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
Greg Clayton1b3815c2013-01-30 00:18:29 +0000414 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
Jim Inghamca36cd12012-10-05 19:16:31 +0000415 {"^(-.*)$", "breakpoint set %1"},
416 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
Greg Clayton722e8852013-02-08 02:54:24 +0000417 {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"},
Jim Inghamca36cd12012-10-05 19:16:31 +0000418 {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}};
419
420 size_t num_regexes = sizeof break_regexes/sizeof(char *[2]);
421
Greg Clayton7b0992d2013-04-18 22:45:39 +0000422 std::unique_ptr<CommandObjectRegexCommand>
Greg Claytona7015092010-09-18 01:14:36 +0000423 break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton8b82f082011-04-12 05:54:46 +0000424 "_regexp-break",
Johnny Chenb417dcd2012-08-23 00:32:22 +0000425 "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
Greg Clayton7d2ef162013-03-29 17:03:23 +0000426 "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
427 2,
428 CommandCompletions::eSymbolCompletion |
429 CommandCompletions::eSourceFileCompletion));
Jim Inghamca36cd12012-10-05 19:16:31 +0000430
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000431 if (break_regex_cmd_ap.get())
432 {
Jim Inghamca36cd12012-10-05 19:16:31 +0000433 bool success = true;
434 for (size_t i = 0; i < num_regexes; i++)
435 {
436 success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]);
437 if (!success)
438 break;
439 }
440 success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
441
442 if (success)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000443 {
444 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
445 m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
446 }
447 }
Jim Inghamffba2292011-03-22 02:29:32 +0000448
Greg Clayton7b0992d2013-04-18 22:45:39 +0000449 std::unique_ptr<CommandObjectRegexCommand>
Jim Inghamca36cd12012-10-05 19:16:31 +0000450 tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this,
451 "_regexp-tbreak",
452 "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
Greg Clayton7d2ef162013-03-29 17:03:23 +0000453 "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
454 2,
455 CommandCompletions::eSymbolCompletion |
456 CommandCompletions::eSourceFileCompletion));
Jim Inghamca36cd12012-10-05 19:16:31 +0000457
458 if (tbreak_regex_cmd_ap.get())
459 {
460 bool success = true;
461 for (size_t i = 0; i < num_regexes; i++)
462 {
463 // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
464 char buffer[1024];
465 int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
466 assert (num_printed < 1024);
467 success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
468 if (!success)
469 break;
470 }
471 success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
472
473 if (success)
474 {
475 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
476 m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp;
477 }
478 }
479
Greg Clayton7b0992d2013-04-18 22:45:39 +0000480 std::unique_ptr<CommandObjectRegexCommand>
Johnny Chen6d675242012-08-24 18:15:45 +0000481 attach_regex_cmd_ap(new CommandObjectRegexCommand (*this,
482 "_regexp-attach",
483 "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.",
Greg Clayton7d2ef162013-03-29 17:03:23 +0000484 "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]",
485 2));
Johnny Chen6d675242012-08-24 18:15:45 +0000486 if (attach_regex_cmd_ap.get())
487 {
Greg Clayton3cb4c7d2012-12-15 01:19:07 +0000488 if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") &&
489 attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach'
490 attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") &&
491 attach_regex_cmd_ap->AddRegexCommand("^$", "process attach"))
Johnny Chen6d675242012-08-24 18:15:45 +0000492 {
493 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release());
494 m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp;
495 }
496 }
497
Greg Clayton7b0992d2013-04-18 22:45:39 +0000498 std::unique_ptr<CommandObjectRegexCommand>
Jim Inghamffba2292011-03-22 02:29:32 +0000499 down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton8b82f082011-04-12 05:54:46 +0000500 "_regexp-down",
501 "Go down \"n\" frames in the stack (1 frame by default).",
502 "_regexp-down [n]", 2));
Jim Inghamffba2292011-03-22 02:29:32 +0000503 if (down_regex_cmd_ap.get())
504 {
505 if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
506 down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1"))
507 {
508 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
509 m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
510 }
511 }
512
Greg Clayton7b0992d2013-04-18 22:45:39 +0000513 std::unique_ptr<CommandObjectRegexCommand>
Jim Inghamffba2292011-03-22 02:29:32 +0000514 up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton8b82f082011-04-12 05:54:46 +0000515 "_regexp-up",
516 "Go up \"n\" frames in the stack (1 frame by default).",
517 "_regexp-up [n]", 2));
Jim Inghamffba2292011-03-22 02:29:32 +0000518 if (up_regex_cmd_ap.get())
519 {
520 if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
521 up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1"))
522 {
523 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
524 m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp;
525 }
526 }
Jason Molendabc7748b2011-10-22 01:30:52 +0000527
Greg Clayton7b0992d2013-04-18 22:45:39 +0000528 std::unique_ptr<CommandObjectRegexCommand>
Jason Molendabc7748b2011-10-22 01:30:52 +0000529 display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton7d2ef162013-03-29 17:03:23 +0000530 "_regexp-display",
531 "Add an expression evaluation stop-hook.",
532 "_regexp-display expression", 2));
Jason Molendabc7748b2011-10-22 01:30:52 +0000533 if (display_regex_cmd_ap.get())
534 {
535 if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
536 {
537 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release());
538 m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp;
539 }
540 }
541
Greg Clayton7b0992d2013-04-18 22:45:39 +0000542 std::unique_ptr<CommandObjectRegexCommand>
Jason Molendabc7748b2011-10-22 01:30:52 +0000543 undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton7d2ef162013-03-29 17:03:23 +0000544 "_regexp-undisplay",
545 "Remove an expression evaluation stop-hook.",
546 "_regexp-undisplay stop-hook-number", 2));
Jason Molendabc7748b2011-10-22 01:30:52 +0000547 if (undisplay_regex_cmd_ap.get())
548 {
549 if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
550 {
551 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release());
552 m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp;
553 }
554 }
555
Greg Clayton7b0992d2013-04-18 22:45:39 +0000556 std::unique_ptr<CommandObjectRegexCommand>
Greg Clayton30c0a1c2012-09-26 22:26:47 +0000557 connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton7d2ef162013-03-29 17:03:23 +0000558 "gdb-remote",
559 "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.",
560 "gdb-remote [<hostname>:]<portnum>", 2));
Greg Clayton30c0a1c2012-09-26 22:26:47 +0000561 if (connect_gdb_remote_cmd_ap.get())
562 {
563 if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") &&
564 connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1"))
565 {
566 CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release());
567 m_command_dict[command_sp->GetCommandName ()] = command_sp;
568 }
569 }
570
Greg Clayton7b0992d2013-04-18 22:45:39 +0000571 std::unique_ptr<CommandObjectRegexCommand>
Greg Clayton30c0a1c2012-09-26 22:26:47 +0000572 connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this,
573 "kdp-remote",
Jason Molendaa7dcb332012-10-23 03:05:16 +0000574 "Connect to a remote KDP server. udp port 41139 is the default port number.",
575 "kdp-remote <hostname>[:<portnum>]", 2));
Greg Clayton30c0a1c2012-09-26 22:26:47 +0000576 if (connect_kdp_remote_cmd_ap.get())
577 {
578 if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
Jason Molendac36b1842012-09-27 02:47:55 +0000579 connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139"))
Greg Clayton30c0a1c2012-09-26 22:26:47 +0000580 {
581 CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
582 m_command_dict[command_sp->GetCommandName ()] = command_sp;
583 }
584 }
585
Greg Clayton7b0992d2013-04-18 22:45:39 +0000586 std::unique_ptr<CommandObjectRegexCommand>
Jason Molenda4cddfed2012-10-05 05:29:32 +0000587 bt_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Jim Ingham71bf2992012-10-10 16:51:31 +0000588 "_regexp-bt",
Jason Molenda4cddfed2012-10-05 05:29:32 +0000589 "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.",
590 "bt [<digit>|all]", 2));
591 if (bt_regex_cmd_ap.get())
592 {
593 // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
594 // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and
595 // so now "bt 3" is the preferred form, in line with gdb.
596 if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") &&
597 bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") &&
598 bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") &&
599 bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace"))
600 {
601 CommandObjectSP command_sp(bt_regex_cmd_ap.release());
602 m_command_dict[command_sp->GetCommandName ()] = command_sp;
603 }
604 }
605
Greg Clayton7b0992d2013-04-18 22:45:39 +0000606 std::unique_ptr<CommandObjectRegexCommand>
Greg Clayton6bade322013-02-01 23:33:03 +0000607 list_regex_cmd_ap(new CommandObjectRegexCommand (*this,
608 "_regexp-list",
609 "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.",
Ben Langmuiredb3b212013-09-26 20:00:01 +0000610 "_regexp-list [<line>]\n_regexp-list [<file>:<line>]\n_regexp-list [<file>:<line>]",
Greg Clayton7d2ef162013-03-29 17:03:23 +0000611 2,
612 CommandCompletions::eSourceFileCompletion));
Greg Clayton6bade322013-02-01 23:33:03 +0000613 if (list_regex_cmd_ap.get())
614 {
615 if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") &&
616 list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") &&
617 list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") &&
Greg Claytond9010962013-02-12 18:42:05 +0000618 list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") &&
Greg Claytone4ca5152013-03-13 18:25:49 +0000619 list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") &&
Greg Clayton6bade322013-02-01 23:33:03 +0000620 list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") &&
621 list_regex_cmd_ap->AddRegexCommand("^$", "source list"))
622 {
623 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release());
624 m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp;
625 }
626 }
627
Greg Clayton7b0992d2013-04-18 22:45:39 +0000628 std::unique_ptr<CommandObjectRegexCommand>
Greg Claytonef5651d2013-02-12 18:52:24 +0000629 env_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton7d2ef162013-03-29 17:03:23 +0000630 "_regexp-env",
631 "Implements a shortcut to viewing and setting environment variables.",
632 "_regexp-env\n_regexp-env FOO=BAR", 2));
Greg Claytonef5651d2013-02-12 18:52:24 +0000633 if (env_regex_cmd_ap.get())
634 {
635 if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") &&
636 env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1"))
637 {
638 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release());
639 m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp;
640 }
641 }
642
Richard Mittonf86248d2013-09-12 02:20:34 +0000643 std::unique_ptr<CommandObjectRegexCommand>
644 jump_regex_cmd_ap(new CommandObjectRegexCommand (*this,
645 "_regexp-jump",
646 "Sets the program counter to a new address.",
647 "_regexp-jump [<line>]\n"
648 "_regexp-jump [<+-lineoffset>]\n"
649 "_regexp-jump [<file>:<line>]\n"
650 "_regexp-jump [*<addr>]\n", 2));
651 if (jump_regex_cmd_ap.get())
652 {
653 if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") &&
654 jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "thread jump --line %1") &&
655 jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", "thread jump --file %1 --line %2") &&
656 jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", "thread jump --by %1"))
657 {
658 CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release());
659 m_command_dict[jump_regex_cmd_sp->GetCommandName ()] = jump_regex_cmd_sp;
660 }
661 }
662
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000663}
664
665int
666CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
667 StringList &matches)
668{
669 CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
670
671 if (include_aliases)
672 {
673 CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
674 }
675
676 return matches.GetSize();
677}
678
679CommandObjectSP
680CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
681{
682 CommandObject::CommandMap::iterator pos;
Greg Claytonc7bece562013-01-25 18:06:21 +0000683 CommandObjectSP command_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000684
685 std::string cmd(cmd_cstr);
686
687 if (HasCommands())
688 {
689 pos = m_command_dict.find(cmd);
690 if (pos != m_command_dict.end())
Greg Claytonc7bece562013-01-25 18:06:21 +0000691 command_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000692 }
693
694 if (include_aliases && HasAliases())
695 {
696 pos = m_alias_dict.find(cmd);
697 if (pos != m_alias_dict.end())
Greg Claytonc7bece562013-01-25 18:06:21 +0000698 command_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000699 }
700
701 if (HasUserCommands())
702 {
703 pos = m_user_dict.find(cmd);
704 if (pos != m_user_dict.end())
Greg Claytonc7bece562013-01-25 18:06:21 +0000705 command_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000706 }
707
Greg Claytonc7bece562013-01-25 18:06:21 +0000708 if (!exact && !command_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000709 {
Jim Ingham279a6c22010-07-06 22:46:59 +0000710 // We will only get into here if we didn't find any exact matches.
711
712 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
713
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000714 StringList local_matches;
Ed Masted78c9572014-04-20 00:31:37 +0000715 if (matches == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000716 matches = &local_matches;
717
Jim Ingham279a6c22010-07-06 22:46:59 +0000718 unsigned int num_cmd_matches = 0;
719 unsigned int num_alias_matches = 0;
720 unsigned int num_user_matches = 0;
721
722 // Look through the command dictionaries one by one, and if we get only one match from any of
723 // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
724
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000725 if (HasCommands())
726 {
727 num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
728 }
729
730 if (num_cmd_matches == 1)
731 {
732 cmd.assign(matches->GetStringAtIndex(0));
733 pos = m_command_dict.find(cmd);
734 if (pos != m_command_dict.end())
Jim Ingham279a6c22010-07-06 22:46:59 +0000735 real_match_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000736 }
737
Jim Ingham490ac552010-06-24 20:28:42 +0000738 if (include_aliases && HasAliases())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000739 {
740 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
741
742 }
743
Jim Ingham279a6c22010-07-06 22:46:59 +0000744 if (num_alias_matches == 1)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000745 {
746 cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
747 pos = m_alias_dict.find(cmd);
748 if (pos != m_alias_dict.end())
Jim Ingham279a6c22010-07-06 22:46:59 +0000749 alias_match_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000750 }
751
Jim Ingham490ac552010-06-24 20:28:42 +0000752 if (HasUserCommands())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000753 {
754 num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
755 }
756
Jim Ingham279a6c22010-07-06 22:46:59 +0000757 if (num_user_matches == 1)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000758 {
759 cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
760
761 pos = m_user_dict.find (cmd);
762 if (pos != m_user_dict.end())
Jim Ingham279a6c22010-07-06 22:46:59 +0000763 user_match_sp = pos->second;
764 }
765
766 // If we got exactly one match, return that, otherwise return the match list.
767
768 if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
769 {
770 if (num_cmd_matches)
771 return real_match_sp;
772 else if (num_alias_matches)
773 return alias_match_sp;
774 else
775 return user_match_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000776 }
777 }
Greg Claytonc7bece562013-01-25 18:06:21 +0000778 else if (matches && command_sp)
Jim Ingham279a6c22010-07-06 22:46:59 +0000779 {
780 matches->AppendString (cmd_cstr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000781 }
782
783
Greg Claytonc7bece562013-01-25 18:06:21 +0000784 return command_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000785}
786
Greg Claytonde164aa2011-04-20 16:37:46 +0000787bool
788CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
789{
790 if (name && name[0])
791 {
792 std::string name_sstr(name);
Enrico Granatae00af802012-10-01 17:19:37 +0000793 bool found = (m_command_dict.find (name_sstr) != m_command_dict.end());
794 if (found && !can_replace)
795 return false;
796 if (found && m_command_dict[name_sstr]->IsRemovable() == false)
Enrico Granata21dfcd92012-09-28 23:57:51 +0000797 return false;
Greg Claytonde164aa2011-04-20 16:37:46 +0000798 m_command_dict[name_sstr] = cmd_sp;
799 return true;
800 }
801 return false;
802}
803
Enrico Granata223383e2011-08-16 23:24:13 +0000804bool
Enrico Granata0a305db2011-11-07 22:57:04 +0000805CommandInterpreter::AddUserCommand (std::string name,
Enrico Granata223383e2011-08-16 23:24:13 +0000806 const lldb::CommandObjectSP &cmd_sp,
807 bool can_replace)
808{
Enrico Granata0a305db2011-11-07 22:57:04 +0000809 if (!name.empty())
Enrico Granata223383e2011-08-16 23:24:13 +0000810 {
Enrico Granata0a305db2011-11-07 22:57:04 +0000811
812 const char* name_cstr = name.c_str();
813
814 // do not allow replacement of internal commands
815 if (CommandExists(name_cstr))
Enrico Granata21dfcd92012-09-28 23:57:51 +0000816 {
817 if (can_replace == false)
818 return false;
819 if (m_command_dict[name]->IsRemovable() == false)
820 return false;
821 }
Enrico Granata0a305db2011-11-07 22:57:04 +0000822
Enrico Granata21dfcd92012-09-28 23:57:51 +0000823 if (UserCommandExists(name_cstr))
824 {
825 if (can_replace == false)
826 return false;
827 if (m_user_dict[name]->IsRemovable() == false)
828 return false;
829 }
830
Enrico Granata0a305db2011-11-07 22:57:04 +0000831 m_user_dict[name] = cmd_sp;
Enrico Granata223383e2011-08-16 23:24:13 +0000832 return true;
833 }
834 return false;
835}
Greg Claytonde164aa2011-04-20 16:37:46 +0000836
Jim Ingham279a6c22010-07-06 22:46:59 +0000837CommandObjectSP
838CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000839{
Caroline Tice472362e2010-12-14 18:51:39 +0000840 Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
841 CommandObjectSP ret_val; // Possibly empty return value.
842
Ed Masted78c9572014-04-20 00:31:37 +0000843 if (cmd_cstr == nullptr)
Caroline Tice472362e2010-12-14 18:51:39 +0000844 return ret_val;
845
846 if (cmd_words.GetArgumentCount() == 1)
Ed Masted78c9572014-04-20 00:31:37 +0000847 return GetCommandSP(cmd_cstr, include_aliases, true, nullptr);
Caroline Tice472362e2010-12-14 18:51:39 +0000848 else
849 {
850 // We have a multi-word command (seemingly), so we need to do more work.
851 // First, get the cmd_obj_sp for the first word in the command.
Ed Masted78c9572014-04-20 00:31:37 +0000852 CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, nullptr);
853 if (cmd_obj_sp.get() != nullptr)
Caroline Tice472362e2010-12-14 18:51:39 +0000854 {
855 // Loop through the rest of the words in the command (everything passed in was supposed to be part of a
856 // command name), and find the appropriate sub-command SP for each command word....
857 size_t end = cmd_words.GetArgumentCount();
858 for (size_t j= 1; j < end; ++j)
859 {
860 if (cmd_obj_sp->IsMultiwordObject())
861 {
Greg Clayton998255b2012-10-13 02:07:45 +0000862 cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
Ed Masted78c9572014-04-20 00:31:37 +0000863 if (cmd_obj_sp.get() == nullptr)
Caroline Tice472362e2010-12-14 18:51:39 +0000864 // The sub-command name was invalid. Fail and return the empty 'ret_val'.
865 return ret_val;
866 }
867 else
868 // We have more words in the command name, but we don't have a multiword object. Fail and return
869 // empty 'ret_val'.
870 return ret_val;
871 }
872 // We successfully looped through all the command words and got valid command objects for them. Assign the
873 // last object retrieved to 'ret_val'.
874 ret_val = cmd_obj_sp;
875 }
876 }
877 return ret_val;
Jim Ingham279a6c22010-07-06 22:46:59 +0000878}
879
880CommandObject *
881CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
882{
883 return GetCommandSPExact (cmd_cstr, include_aliases).get();
884}
885
886CommandObject *
887CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
888{
889 CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
890
891 // If we didn't find an exact match to the command string in the commands, look in
892 // the aliases.
Enrico Granata5342c442013-06-18 18:01:08 +0000893
894 if (command_obj)
895 return command_obj;
Jim Ingham279a6c22010-07-06 22:46:59 +0000896
Enrico Granata5342c442013-06-18 18:01:08 +0000897 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
Jim Ingham279a6c22010-07-06 22:46:59 +0000898
Enrico Granata5342c442013-06-18 18:01:08 +0000899 if (command_obj)
900 return command_obj;
901
902 // If there wasn't an exact match then look for an inexact one in just the commands
Ed Masted78c9572014-04-20 00:31:37 +0000903 command_obj = GetCommandSP(cmd_cstr, false, false, nullptr).get();
Matt Kopec038ff812013-04-23 16:17:32 +0000904
905 // Finally, if there wasn't an inexact match among the commands, look for an inexact
906 // match in both the commands and aliases.
Enrico Granata5342c442013-06-18 18:01:08 +0000907
908 if (command_obj)
909 {
910 if (matches)
911 matches->AppendString(command_obj->GetCommandName());
912 return command_obj;
913 }
914
915 return GetCommandSP(cmd_cstr, true, false, matches).get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000916}
917
918bool
919CommandInterpreter::CommandExists (const char *cmd)
920{
921 return m_command_dict.find(cmd) != m_command_dict.end();
922}
923
924bool
Caroline Ticeca90c472011-05-06 21:37:15 +0000925CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
926 const char *options_args,
927 OptionArgVectorSP &option_arg_vector_sp)
928{
929 bool success = true;
930 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
931
932 if (!options_args || (strlen (options_args) < 1))
933 return true;
934
935 std::string options_string (options_args);
936 Args args (options_args);
937 CommandReturnObject result;
938 // Check to see if the command being aliased can take any command options.
939 Options *options = cmd_obj_sp->GetOptions ();
940 if (options)
941 {
942 // See if any options were specified as part of the alias; if so, handle them appropriately.
943 options->NotifyOptionParsingStarting ();
944 args.Unshift ("dummy_arg");
945 args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
946 args.Shift ();
947 if (result.Succeeded())
948 options->VerifyPartialOptions (result);
949 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
950 {
951 result.AppendError ("Unable to create requested alias.\n");
952 return false;
953 }
954 }
955
Greg Clayton5521f992011-10-28 21:38:01 +0000956 if (!options_string.empty())
Caroline Ticeca90c472011-05-06 21:37:15 +0000957 {
958 if (cmd_obj_sp->WantsRawCommandString ())
959 option_arg_vector->push_back (OptionArgPair ("<argument>",
960 OptionArgValue (-1,
961 options_string)));
962 else
963 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000964 const size_t argc = args.GetArgumentCount();
Caroline Ticeca90c472011-05-06 21:37:15 +0000965 for (size_t i = 0; i < argc; ++i)
966 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
967 option_arg_vector->push_back
968 (OptionArgPair ("<argument>",
969 OptionArgValue (-1,
970 std::string (args.GetArgumentAtIndex (i)))));
971 }
972 }
973
974 return success;
975}
976
977bool
Jim Ingham298f3782013-04-03 00:25:49 +0000978CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
979{
980 bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end());
981 if (exact_match)
982 {
983 full_name.assign(cmd);
984 return exact_match;
985 }
986 else
987 {
988 StringList matches;
989 size_t num_alias_matches;
990 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
991 if (num_alias_matches == 1)
992 {
993 // Make sure this isn't shadowing a command in the regular command space:
994 StringList regular_matches;
995 const bool include_aliases = false;
996 const bool exact = false;
997 CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, &regular_matches));
998 if (cmd_obj_sp || regular_matches.GetSize() > 0)
999 return false;
1000 else
1001 {
1002 full_name.assign (matches.GetStringAtIndex(0));
1003 return true;
1004 }
1005 }
1006 else
1007 return false;
1008 }
1009}
1010
1011bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001012CommandInterpreter::AliasExists (const char *cmd)
1013{
1014 return m_alias_dict.find(cmd) != m_alias_dict.end();
1015}
1016
1017bool
1018CommandInterpreter::UserCommandExists (const char *cmd)
1019{
1020 return m_user_dict.find(cmd) != m_user_dict.end();
1021}
1022
1023void
1024CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
1025{
Jim Ingham279a6c22010-07-06 22:46:59 +00001026 command_obj_sp->SetIsAlias (true);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001027 m_alias_dict[alias_name] = command_obj_sp;
1028}
1029
1030bool
1031CommandInterpreter::RemoveAlias (const char *alias_name)
1032{
1033 CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
1034 if (pos != m_alias_dict.end())
1035 {
1036 m_alias_dict.erase(pos);
1037 return true;
1038 }
1039 return false;
1040}
1041bool
1042CommandInterpreter::RemoveUser (const char *alias_name)
1043{
1044 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
1045 if (pos != m_user_dict.end())
1046 {
1047 m_user_dict.erase(pos);
1048 return true;
1049 }
1050 return false;
1051}
1052
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001053void
1054CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
1055{
1056 help_string.Printf ("'%s", command_name);
1057 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1058
Sean Callanan9a028512012-08-09 00:50:26 +00001059 if (option_arg_vector_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001060 {
1061 OptionArgVector *options = option_arg_vector_sp.get();
Andy Gibbsa297a972013-06-19 19:04:53 +00001062 for (size_t i = 0; i < options->size(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001063 {
1064 OptionArgPair cur_option = (*options)[i];
1065 std::string opt = cur_option.first;
Caroline Ticed9d63362010-12-07 19:58:26 +00001066 OptionArgValue value_pair = cur_option.second;
1067 std::string value = value_pair.second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001068 if (opt.compare("<argument>") == 0)
1069 {
1070 help_string.Printf (" %s", value.c_str());
1071 }
1072 else
1073 {
1074 help_string.Printf (" %s", opt.c_str());
1075 if ((value.compare ("<no-argument>") != 0)
1076 && (value.compare ("<need-argument") != 0))
1077 {
1078 help_string.Printf (" %s", value.c_str());
1079 }
1080 }
1081 }
1082 }
1083
1084 help_string.Printf ("'");
1085}
1086
Greg Clayton12fc3e02010-08-26 22:05:43 +00001087size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001088CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
1089{
1090 CommandObject::CommandMap::const_iterator pos;
Greg Clayton12fc3e02010-08-26 22:05:43 +00001091 CommandObject::CommandMap::const_iterator end = dict.end();
1092 size_t max_len = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001093
Greg Clayton12fc3e02010-08-26 22:05:43 +00001094 for (pos = dict.begin(); pos != end; ++pos)
1095 {
1096 size_t len = pos->first.size();
1097 if (max_len < len)
1098 max_len = len;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001099 }
Greg Clayton12fc3e02010-08-26 22:05:43 +00001100 return max_len;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001101}
1102
1103void
Enrico Granata223383e2011-08-16 23:24:13 +00001104CommandInterpreter::GetHelp (CommandReturnObject &result,
Enrico Granata08633ee2011-09-09 17:49:36 +00001105 uint32_t cmd_types)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001106{
1107 CommandObject::CommandMap::const_iterator pos;
Greg Claytonc7bece562013-01-25 18:06:21 +00001108 size_t max_len = FindLongestCommandWord (m_command_dict);
Enrico Granata223383e2011-08-16 23:24:13 +00001109
1110 if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001111 {
Enrico Granata223383e2011-08-16 23:24:13 +00001112
1113 result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
1114 result.AppendMessage("");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001115
Enrico Granata223383e2011-08-16 23:24:13 +00001116 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
1117 {
1118 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1119 max_len);
1120 }
1121 result.AppendMessage("");
1122
1123 }
1124
Greg Clayton5521f992011-10-28 21:38:01 +00001125 if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001126 {
Jim Ingham49e80a12010-10-22 18:47:16 +00001127 result.AppendMessage("The following is a list of your current command abbreviations "
Johnny Chenb89982d2011-04-21 00:39:18 +00001128 "(see 'help command alias' for more info):");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001129 result.AppendMessage("");
Greg Clayton12fc3e02010-08-26 22:05:43 +00001130 max_len = FindLongestCommandWord (m_alias_dict);
1131
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001132 for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
1133 {
1134 StreamString sstr;
1135 StreamString translation_and_help;
1136 std::string entry_name = pos->first;
1137 std::string second_entry = pos->second.get()->GetCommandName();
1138 GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
1139
1140 translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp());
1141 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
1142 translation_and_help.GetData(), max_len);
1143 }
1144 result.AppendMessage("");
1145 }
1146
Greg Clayton5521f992011-10-28 21:38:01 +00001147 if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001148 {
1149 result.AppendMessage ("The following is a list of your current user-defined commands:");
1150 result.AppendMessage("");
Enrico Granata223383e2011-08-16 23:24:13 +00001151 max_len = FindLongestCommandWord (m_user_dict);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001152 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
1153 {
Enrico Granata223383e2011-08-16 23:24:13 +00001154 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1155 max_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001156 }
1157 result.AppendMessage("");
1158 }
1159
1160 result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
1161}
1162
Caroline Tice844d2302010-12-09 22:52:49 +00001163CommandObject *
1164CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001165{
Caroline Tice844d2302010-12-09 22:52:49 +00001166 // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
1167 // eventually be invoked by the given command line.
1168
Ed Masted78c9572014-04-20 00:31:37 +00001169 CommandObject *cmd_obj = nullptr;
Caroline Tice844d2302010-12-09 22:52:49 +00001170 std::string white_space (" \t\v");
1171 size_t start = command_string.find_first_not_of (white_space);
1172 size_t end = 0;
1173 bool done = false;
1174 while (!done)
1175 {
1176 if (start != std::string::npos)
1177 {
1178 // Get the next word from command_string.
1179 end = command_string.find_first_of (white_space, start);
1180 if (end == std::string::npos)
1181 end = command_string.size();
1182 std::string cmd_word = command_string.substr (start, end - start);
1183
Ed Masted78c9572014-04-20 00:31:37 +00001184 if (cmd_obj == nullptr)
Caroline Tice844d2302010-12-09 22:52:49 +00001185 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
1186 // command or alias.
1187 cmd_obj = GetCommandObject (cmd_word.c_str());
1188 else if (cmd_obj->IsMultiwordObject ())
1189 {
1190 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
Greg Clayton998255b2012-10-13 02:07:45 +00001191 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001192 if (sub_cmd_obj)
1193 cmd_obj = sub_cmd_obj;
1194 else // cmd_word was not a valid sub-command word, so we are donee
1195 done = true;
1196 }
1197 else
1198 // We have a cmd_obj and it is not a multi-word object, so we are done.
1199 done = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001200
Caroline Tice844d2302010-12-09 22:52:49 +00001201 // If we didn't find a valid command object, or our command object is not a multi-word object, or
1202 // we are at the end of the command_string, then we are done. Otherwise, find the start of the
1203 // next word.
1204
1205 if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
1206 done = true;
1207 else
1208 start = command_string.find_first_not_of (white_space, end);
1209 }
1210 else
1211 // Unable to find any more words.
1212 done = true;
1213 }
1214
1215 if (end == command_string.size())
1216 command_string.clear();
1217 else
1218 command_string = command_string.substr(end);
1219
1220 return cmd_obj;
1221}
1222
Greg Clayton51964162011-10-25 00:36:27 +00001223static const char *k_white_space = " \t\v";
Greg Clayton5521f992011-10-28 21:38:01 +00001224static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
Greg Clayton51964162011-10-25 00:36:27 +00001225static void
1226StripLeadingSpaces (std::string &s)
Caroline Tice844d2302010-12-09 22:52:49 +00001227{
Greg Clayton51964162011-10-25 00:36:27 +00001228 if (!s.empty())
Caroline Tice844d2302010-12-09 22:52:49 +00001229 {
Greg Clayton51964162011-10-25 00:36:27 +00001230 size_t pos = s.find_first_not_of (k_white_space);
1231 if (pos == std::string::npos)
1232 s.clear();
1233 else if (pos == 0)
1234 return;
1235 s.erase (0, pos);
1236 }
1237}
1238
Greg Clayton93c62e62011-11-09 23:25:03 +00001239static size_t
1240FindArgumentTerminator (const std::string &s)
1241{
Greg Clayton93c62e62011-11-09 23:25:03 +00001242 const size_t s_len = s.size();
1243 size_t offset = 0;
1244 while (offset < s_len)
1245 {
1246 size_t pos = s.find ("--", offset);
1247 if (pos == std::string::npos)
1248 break;
1249 if (pos > 0)
1250 {
1251 if (isspace(s[pos-1]))
1252 {
1253 // Check if the string ends "\s--" (where \s is a space character)
1254 // or if we have "\s--\s".
1255 if ((pos + 2 >= s_len) || isspace(s[pos+2]))
1256 {
Greg Clayton93c62e62011-11-09 23:25:03 +00001257 return pos;
1258 }
1259 }
1260 }
1261 offset = pos + 2;
1262 }
Greg Clayton93c62e62011-11-09 23:25:03 +00001263 return std::string::npos;
1264}
1265
Greg Clayton51964162011-10-25 00:36:27 +00001266static bool
Greg Clayton5521f992011-10-28 21:38:01 +00001267ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char &quote_char)
Greg Clayton51964162011-10-25 00:36:27 +00001268{
Greg Clayton5521f992011-10-28 21:38:01 +00001269 command.clear();
1270 suffix.clear();
Greg Clayton51964162011-10-25 00:36:27 +00001271 StripLeadingSpaces (command_string);
1272
1273 bool result = false;
1274 quote_char = '\0';
1275
1276 if (!command_string.empty())
1277 {
1278 const char first_char = command_string[0];
1279 if (first_char == '\'' || first_char == '"')
Caroline Tice844d2302010-12-09 22:52:49 +00001280 {
Greg Clayton51964162011-10-25 00:36:27 +00001281 quote_char = first_char;
1282 const size_t end_quote_pos = command_string.find (quote_char, 1);
1283 if (end_quote_pos == std::string::npos)
Caroline Tice2b5e8502011-05-11 16:07:06 +00001284 {
Greg Clayton5521f992011-10-28 21:38:01 +00001285 command.swap (command_string);
Greg Clayton51964162011-10-25 00:36:27 +00001286 command_string.erase ();
Caroline Tice2b5e8502011-05-11 16:07:06 +00001287 }
1288 else
1289 {
Greg Clayton5521f992011-10-28 21:38:01 +00001290 command.assign (command_string, 1, end_quote_pos - 1);
Greg Clayton51964162011-10-25 00:36:27 +00001291 if (end_quote_pos + 1 < command_string.size())
1292 command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
1293 else
1294 command_string.erase ();
Caroline Tice2b5e8502011-05-11 16:07:06 +00001295 }
Caroline Tice844d2302010-12-09 22:52:49 +00001296 }
1297 else
1298 {
Greg Clayton51964162011-10-25 00:36:27 +00001299 const size_t first_space_pos = command_string.find_first_of (k_white_space);
1300 if (first_space_pos == std::string::npos)
Caroline Tice2b5e8502011-05-11 16:07:06 +00001301 {
Greg Clayton5521f992011-10-28 21:38:01 +00001302 command.swap (command_string);
Greg Clayton51964162011-10-25 00:36:27 +00001303 command_string.erase();
Caroline Tice2b5e8502011-05-11 16:07:06 +00001304 }
1305 else
1306 {
Greg Clayton5521f992011-10-28 21:38:01 +00001307 command.assign (command_string, 0, first_space_pos);
1308 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
Caroline Tice2b5e8502011-05-11 16:07:06 +00001309 }
Caroline Tice844d2302010-12-09 22:52:49 +00001310 }
Greg Clayton51964162011-10-25 00:36:27 +00001311 result = true;
Caroline Tice844d2302010-12-09 22:52:49 +00001312 }
Greg Clayton5521f992011-10-28 21:38:01 +00001313
1314
1315 if (!command.empty())
1316 {
1317 // actual commands can't start with '-' or '_'
1318 if (command[0] != '-' && command[0] != '_')
1319 {
1320 size_t pos = command.find_first_not_of(k_valid_command_chars);
1321 if (pos > 0 && pos != std::string::npos)
1322 {
1323 suffix.assign (command.begin() + pos, command.end());
1324 command.erase (pos);
1325 }
1326 }
1327 }
Greg Clayton51964162011-10-25 00:36:27 +00001328
1329 return result;
Caroline Tice844d2302010-12-09 22:52:49 +00001330}
1331
Greg Clayton5521f992011-10-28 21:38:01 +00001332CommandObject *
1333CommandInterpreter::BuildAliasResult (const char *alias_name,
1334 std::string &raw_input_string,
1335 std::string &alias_result,
1336 CommandReturnObject &result)
Caroline Tice844d2302010-12-09 22:52:49 +00001337{
Ed Masted78c9572014-04-20 00:31:37 +00001338 CommandObject *alias_cmd_obj = nullptr;
Caroline Tice844d2302010-12-09 22:52:49 +00001339 Args cmd_args (raw_input_string.c_str());
1340 alias_cmd_obj = GetCommandObject (alias_name);
1341 StreamString result_str;
1342
1343 if (alias_cmd_obj)
1344 {
1345 std::string alias_name_str = alias_name;
1346 if ((cmd_args.GetArgumentCount() == 0)
1347 || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
1348 cmd_args.Unshift (alias_name);
1349
1350 result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
1351 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1352
1353 if (option_arg_vector_sp.get())
1354 {
1355 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1356
Andy Gibbsa297a972013-06-19 19:04:53 +00001357 for (size_t i = 0; i < option_arg_vector->size(); ++i)
Caroline Tice844d2302010-12-09 22:52:49 +00001358 {
1359 OptionArgPair option_pair = (*option_arg_vector)[i];
1360 OptionArgValue value_pair = option_pair.second;
1361 int value_type = value_pair.first;
1362 std::string option = option_pair.first;
1363 std::string value = value_pair.second;
1364 if (option.compare ("<argument>") == 0)
1365 result_str.Printf (" %s", value.c_str());
1366 else
1367 {
1368 result_str.Printf (" %s", option.c_str());
Virgile Belloe2607b52013-09-05 16:42:23 +00001369 if (value_type != OptionParser::eOptionalArgument)
Caroline Tice844d2302010-12-09 22:52:49 +00001370 result_str.Printf (" ");
Virgile Belloe2607b52013-09-05 16:42:23 +00001371 if (value.compare ("<OptionParser::eNoArgument>") != 0)
Caroline Tice844d2302010-12-09 22:52:49 +00001372 {
1373 int index = GetOptionArgumentPosition (value.c_str());
1374 if (index == 0)
1375 result_str.Printf ("%s", value.c_str());
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +00001376 else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())
Caroline Tice844d2302010-12-09 22:52:49 +00001377 {
1378
1379 result.AppendErrorWithFormat
1380 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
1381 index);
1382 result.SetStatus (eReturnStatusFailed);
Greg Clayton5521f992011-10-28 21:38:01 +00001383 return alias_cmd_obj;
Caroline Tice844d2302010-12-09 22:52:49 +00001384 }
1385 else
1386 {
1387 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
1388 if (strpos != std::string::npos)
1389 raw_input_string = raw_input_string.erase (strpos,
1390 strlen (cmd_args.GetArgumentAtIndex (index)));
1391 result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
1392 }
1393 }
1394 }
1395 }
1396 }
1397
1398 alias_result = result_str.GetData();
1399 }
Greg Clayton5521f992011-10-28 21:38:01 +00001400 return alias_cmd_obj;
Caroline Tice844d2302010-12-09 22:52:49 +00001401}
1402
Greg Clayton5a314712011-10-14 07:41:33 +00001403Error
1404CommandInterpreter::PreprocessCommand (std::string &command)
1405{
1406 // The command preprocessor needs to do things to the command
1407 // line before any parsing of arguments or anything else is done.
1408 // The only current stuff that gets proprocessed is anyting enclosed
1409 // in backtick ('`') characters is evaluated as an expression and
1410 // the result of the expression must be a scalar that can be substituted
1411 // into the command. An example would be:
1412 // (lldb) memory read `$rsp + 20`
1413 Error error; // Error for any expressions that might not evaluate
1414 size_t start_backtick;
1415 size_t pos = 0;
1416 while ((start_backtick = command.find ('`', pos)) != std::string::npos)
1417 {
1418 if (start_backtick > 0 && command[start_backtick-1] == '\\')
1419 {
1420 // The backtick was preceeded by a '\' character, remove the slash
1421 // and don't treat the backtick as the start of an expression
1422 command.erase(start_backtick-1, 1);
1423 // No need to add one to start_backtick since we just deleted a char
1424 pos = start_backtick;
1425 }
1426 else
1427 {
1428 const size_t expr_content_start = start_backtick + 1;
1429 const size_t end_backtick = command.find ('`', expr_content_start);
1430 if (end_backtick == std::string::npos)
1431 return error;
1432 else if (end_backtick == expr_content_start)
1433 {
1434 // Empty expression (two backticks in a row)
1435 command.erase (start_backtick, 2);
1436 }
1437 else
1438 {
1439 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
1440
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00001441 ExecutionContext exe_ctx(GetExecutionContext());
1442 Target *target = exe_ctx.GetTargetPtr();
Johnny Chen51ea0ad2011-10-29 00:21:50 +00001443 // Get a dummy target to allow for calculator mode while processing backticks.
1444 // This also helps break the infinite loop caused when target is null.
1445 if (!target)
1446 target = Host::GetDummyTarget(GetDebugger()).get();
Greg Clayton5a314712011-10-14 07:41:33 +00001447 if (target)
1448 {
Greg Clayton5a314712011-10-14 07:41:33 +00001449 ValueObjectSP expr_result_valobj_sp;
Enrico Granatad4439aa2012-09-05 20:41:26 +00001450
Jim Ingham35e1bda2012-10-16 21:41:58 +00001451 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +00001452 options.SetCoerceToId(false);
1453 options.SetUnwindOnError(true);
1454 options.SetIgnoreBreakpoints(true);
1455 options.SetKeepInMemory(false);
1456 options.SetTryAllThreads(true);
1457 options.SetTimeoutUsec(0);
Enrico Granatad4439aa2012-09-05 20:41:26 +00001458
Greg Clayton5a314712011-10-14 07:41:33 +00001459 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
Enrico Granatad4439aa2012-09-05 20:41:26 +00001460 exe_ctx.GetFramePtr(),
Enrico Granata3372f582012-07-16 23:10:35 +00001461 expr_result_valobj_sp,
Enrico Granatad4439aa2012-09-05 20:41:26 +00001462 options);
1463
Greg Clayton5a314712011-10-14 07:41:33 +00001464 if (expr_result == eExecutionCompleted)
1465 {
1466 Scalar scalar;
1467 if (expr_result_valobj_sp->ResolveValue (scalar))
1468 {
1469 command.erase (start_backtick, end_backtick - start_backtick + 1);
1470 StreamString value_strm;
1471 const bool show_type = false;
1472 scalar.GetValue (&value_strm, show_type);
1473 size_t value_string_size = value_strm.GetSize();
1474 if (value_string_size)
1475 {
1476 command.insert (start_backtick, value_strm.GetData(), value_string_size);
1477 pos = start_backtick + value_string_size;
1478 continue;
1479 }
1480 else
1481 {
1482 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1483 }
1484 }
1485 else
1486 {
1487 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1488 }
1489 }
1490 else
1491 {
1492 if (expr_result_valobj_sp)
1493 error = expr_result_valobj_sp->GetError();
1494 if (error.Success())
1495 {
1496
1497 switch (expr_result)
1498 {
1499 case eExecutionSetupError:
1500 error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
1501 break;
1502 case eExecutionCompleted:
1503 break;
1504 case eExecutionDiscarded:
1505 error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
1506 break;
1507 case eExecutionInterrupted:
1508 error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
1509 break;
Jim Ingham184e9812013-01-15 02:47:48 +00001510 case eExecutionHitBreakpoint:
1511 error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
1512 break;
Greg Clayton5a314712011-10-14 07:41:33 +00001513 case eExecutionTimedOut:
1514 error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
1515 break;
Greg Claytonc28ce782013-11-08 23:38:26 +00001516 case eExecutionStoppedForDebug:
1517 error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str());
1518 break;
Greg Clayton5a314712011-10-14 07:41:33 +00001519 }
1520 }
1521 }
1522 }
1523 }
1524 if (error.Fail())
1525 break;
1526 }
1527 }
1528 return error;
1529}
1530
1531
Caroline Tice844d2302010-12-09 22:52:49 +00001532bool
1533CommandInterpreter::HandleCommand (const char *command_line,
Enrico Granata5f5ab602012-05-31 01:09:06 +00001534 LazyBool lazy_add_to_history,
Caroline Tice844d2302010-12-09 22:52:49 +00001535 CommandReturnObject &result,
Jim Inghame16c50a2011-02-18 00:54:25 +00001536 ExecutionContext *override_context,
Johnny Chen80fdd7c2011-10-05 00:42:59 +00001537 bool repeat_on_empty_command,
1538 bool no_context_switching)
Jim Inghame16c50a2011-02-18 00:54:25 +00001539
Caroline Tice844d2302010-12-09 22:52:49 +00001540{
Jim Inghame16c50a2011-02-18 00:54:25 +00001541
Caroline Tice844d2302010-12-09 22:52:49 +00001542 bool done = false;
Ed Masted78c9572014-04-20 00:31:37 +00001543 CommandObject *cmd_obj = nullptr;
Caroline Tice844d2302010-12-09 22:52:49 +00001544 bool wants_raw_input = false;
1545 std::string command_string (command_line);
Jim Inghama5a97eb2011-07-12 03:12:18 +00001546 std::string original_command_string (command_line);
Caroline Tice844d2302010-12-09 22:52:49 +00001547
Greg Clayton5160ce52013-03-27 23:08:40 +00001548 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
Greg Clayton2d95dc9b2010-11-10 04:57:04 +00001549 Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
1550
1551 // Make a scoped cleanup object that will clear the crash description string
1552 // on exit of this function.
Ed Masted78c9572014-04-20 00:31:37 +00001553 lldb_utility::CleanUp <const char *> crash_description_cleanup(nullptr, Host::SetCrashDescription);
Greg Clayton2d95dc9b2010-11-10 04:57:04 +00001554
Caroline Tice844d2302010-12-09 22:52:49 +00001555 if (log)
1556 log->Printf ("Processing command: %s", command_line);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001557
Jim Ingham30244832010-11-04 23:08:45 +00001558 Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
1559
Johnny Chen80fdd7c2011-10-05 00:42:59 +00001560 if (!no_context_switching)
1561 UpdateExecutionContext (override_context);
Enrico Granata5f5ab602012-05-31 01:09:06 +00001562
Enrico Granata5f5ab602012-05-31 01:09:06 +00001563 bool add_to_history;
1564 if (lazy_add_to_history == eLazyBoolCalculate)
1565 add_to_history = (m_command_source_depth == 0);
1566 else
1567 add_to_history = (lazy_add_to_history == eLazyBoolYes);
1568
Jim Inghame16c50a2011-02-18 00:54:25 +00001569 bool empty_command = false;
1570 bool comment_command = false;
1571 if (command_string.empty())
1572 empty_command = true;
1573 else
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001574 {
Jim Inghame16c50a2011-02-18 00:54:25 +00001575 const char *k_space_characters = "\t\n\v\f\r ";
1576
1577 size_t non_space = command_string.find_first_not_of (k_space_characters);
1578 // Check for empty line or comment line (lines whose first
1579 // non-space character is the comment character for this interpreter)
1580 if (non_space == std::string::npos)
1581 empty_command = true;
1582 else if (command_string[non_space] == m_comment_char)
1583 comment_command = true;
Enrico Granata7594f142013-06-17 22:51:50 +00001584 else if (command_string[non_space] == CommandHistory::g_repeat_char)
Jim Inghama5a97eb2011-07-12 03:12:18 +00001585 {
Enrico Granata7594f142013-06-17 22:51:50 +00001586 const char *history_string = m_command_history.FindString(command_string.c_str() + non_space);
Ed Masted78c9572014-04-20 00:31:37 +00001587 if (history_string == nullptr)
Jim Inghama5a97eb2011-07-12 03:12:18 +00001588 {
1589 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
1590 result.SetStatus(eReturnStatusFailed);
1591 return false;
1592 }
1593 add_to_history = false;
1594 command_string = history_string;
1595 original_command_string = history_string;
1596 }
Jim Inghame16c50a2011-02-18 00:54:25 +00001597 }
1598
1599 if (empty_command)
1600 {
1601 if (repeat_on_empty_command)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001602 {
Enrico Granata7594f142013-06-17 22:51:50 +00001603 if (m_command_history.IsEmpty())
Jim Inghame16c50a2011-02-18 00:54:25 +00001604 {
1605 result.AppendError ("empty command");
1606 result.SetStatus(eReturnStatusFailed);
1607 return false;
1608 }
1609 else
1610 {
1611 command_line = m_repeat_command.c_str();
1612 command_string = command_line;
Jim Inghama5a97eb2011-07-12 03:12:18 +00001613 original_command_string = command_line;
Jim Inghame16c50a2011-02-18 00:54:25 +00001614 if (m_repeat_command.empty())
1615 {
1616 result.AppendErrorWithFormat("No auto repeat.\n");
1617 result.SetStatus (eReturnStatusFailed);
1618 return false;
1619 }
1620 }
1621 add_to_history = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001622 }
1623 else
1624 {
Jim Inghame16c50a2011-02-18 00:54:25 +00001625 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1626 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001627 }
Jim Inghame16c50a2011-02-18 00:54:25 +00001628 }
1629 else if (comment_command)
1630 {
1631 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1632 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001633 }
Caroline Tice2b5e8502011-05-11 16:07:06 +00001634
Greg Clayton5a314712011-10-14 07:41:33 +00001635
1636 Error error (PreprocessCommand (command_string));
1637
1638 if (error.Fail())
1639 {
1640 result.AppendError (error.AsCString());
1641 result.SetStatus(eReturnStatusFailed);
1642 return false;
1643 }
Caroline Tice844d2302010-12-09 22:52:49 +00001644 // Phase 1.
1645
1646 // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
1647 // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that
1648 // the user could have specified an alias, and in translating the alias there may also be command options and/or
1649 // even data (including raw text strings) that need to be found and inserted into the command line as part of
1650 // the translation. So this first step is plain look-up & replacement, resulting in three things: 1). the command
Greg Clayton710dd5a2011-01-08 20:28:42 +00001651 // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
Caroline Tice844d2302010-12-09 22:52:49 +00001652 // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
Caroline Ticed9d63362010-12-07 19:58:26 +00001653
Caroline Tice844d2302010-12-09 22:52:49 +00001654 StreamString revised_command_line;
Caroline Tice01274c02010-12-11 08:16:56 +00001655 size_t actual_cmd_name_len = 0;
Greg Clayton5521f992011-10-28 21:38:01 +00001656 std::string next_word;
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001657 StringList matches;
Caroline Tice844d2302010-12-09 22:52:49 +00001658 while (!done)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001659 {
Caroline Tice2b5e8502011-05-11 16:07:06 +00001660 char quote_char = '\0';
Greg Clayton5521f992011-10-28 21:38:01 +00001661 std::string suffix;
1662 ExtractCommand (command_string, next_word, suffix, quote_char);
Ed Masted78c9572014-04-20 00:31:37 +00001663 if (cmd_obj == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001664 {
Jim Ingham298f3782013-04-03 00:25:49 +00001665 std::string full_name;
1666 if (GetAliasFullName(next_word.c_str(), full_name))
Caroline Tice472362e2010-12-14 18:51:39 +00001667 {
Greg Clayton5521f992011-10-28 21:38:01 +00001668 std::string alias_result;
Jim Ingham298f3782013-04-03 00:25:49 +00001669 cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result);
Greg Clayton5521f992011-10-28 21:38:01 +00001670 revised_command_line.Printf ("%s", alias_result.c_str());
1671 if (cmd_obj)
1672 {
1673 wants_raw_input = cmd_obj->WantsRawCommandString ();
1674 actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
1675 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001676 }
1677 else
1678 {
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001679 cmd_obj = GetCommandObject (next_word.c_str(), &matches);
Greg Clayton5521f992011-10-28 21:38:01 +00001680 if (cmd_obj)
1681 {
1682 actual_cmd_name_len += next_word.length();
1683 revised_command_line.Printf ("%s", next_word.c_str());
1684 wants_raw_input = cmd_obj->WantsRawCommandString ();
1685 }
Caroline Tice2b5e8502011-05-11 16:07:06 +00001686 else
Greg Clayton5521f992011-10-28 21:38:01 +00001687 {
1688 revised_command_line.Printf ("%s", next_word.c_str());
1689 }
Caroline Tice844d2302010-12-09 22:52:49 +00001690 }
1691 }
1692 else
1693 {
Greg Clayton5521f992011-10-28 21:38:01 +00001694 if (cmd_obj->IsMultiwordObject ())
1695 {
Greg Clayton998255b2012-10-13 02:07:45 +00001696 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str());
Greg Clayton5521f992011-10-28 21:38:01 +00001697 if (sub_cmd_obj)
1698 {
1699 actual_cmd_name_len += next_word.length() + 1;
1700 revised_command_line.Printf (" %s", next_word.c_str());
1701 cmd_obj = sub_cmd_obj;
1702 wants_raw_input = cmd_obj->WantsRawCommandString ();
1703 }
1704 else
1705 {
1706 if (quote_char)
1707 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1708 else
1709 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1710 done = true;
1711 }
1712 }
Caroline Tice2b5e8502011-05-11 16:07:06 +00001713 else
Greg Clayton5521f992011-10-28 21:38:01 +00001714 {
1715 if (quote_char)
1716 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1717 else
1718 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1719 done = true;
1720 }
Caroline Tice844d2302010-12-09 22:52:49 +00001721 }
1722
Ed Masted78c9572014-04-20 00:31:37 +00001723 if (cmd_obj == nullptr)
Caroline Tice844d2302010-12-09 22:52:49 +00001724 {
Greg Claytonc7bece562013-01-25 18:06:21 +00001725 const size_t num_matches = matches.GetSize();
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001726 if (matches.GetSize() > 1) {
Greg Claytonc7bece562013-01-25 18:06:21 +00001727 StreamString error_msg;
1728 error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001729
1730 for (uint32_t i = 0; i < num_matches; ++i) {
Greg Claytonc7bece562013-01-25 18:06:21 +00001731 error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i));
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001732 }
Greg Claytonc7bece562013-01-25 18:06:21 +00001733 result.AppendRawError (error_msg.GetString().c_str());
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001734 } else {
1735 // We didn't have only one match, otherwise we wouldn't get here.
1736 assert(num_matches == 0);
1737 result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
1738 }
Caroline Tice844d2302010-12-09 22:52:49 +00001739 result.SetStatus (eReturnStatusFailed);
1740 return false;
1741 }
1742
Greg Clayton5521f992011-10-28 21:38:01 +00001743 if (cmd_obj->IsMultiwordObject ())
1744 {
1745 if (!suffix.empty())
1746 {
1747
Enrico Granataaded51d2013-06-12 00:44:43 +00001748 result.AppendErrorWithFormat ("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n",
1749 cmd_obj->GetCommandName(),
1750 next_word.empty() ? "" : next_word.c_str(),
1751 next_word.empty() ? " -- " : " ",
Greg Clayton5521f992011-10-28 21:38:01 +00001752 suffix.c_str());
1753 result.SetStatus (eReturnStatusFailed);
1754 return false;
1755 }
1756 }
1757 else
1758 {
1759 // If we found a normal command, we are done
1760 done = true;
1761 if (!suffix.empty())
1762 {
1763 switch (suffix[0])
1764 {
1765 case '/':
1766 // GDB format suffixes
Greg Clayton52ec56c2011-10-29 00:57:28 +00001767 {
1768 Options *command_options = cmd_obj->GetOptions();
1769 if (command_options && command_options->SupportsLongOption("gdb-format"))
1770 {
Greg Clayton93c62e62011-11-09 23:25:03 +00001771 std::string gdb_format_option ("--gdb-format=");
1772 gdb_format_option += (suffix.c_str() + 1);
1773
1774 bool inserted = false;
1775 std::string &cmd = revised_command_line.GetString();
1776 size_t arg_terminator_idx = FindArgumentTerminator (cmd);
1777 if (arg_terminator_idx != std::string::npos)
1778 {
1779 // Insert the gdb format option before the "--" that terminates options
1780 gdb_format_option.append(1,' ');
1781 cmd.insert(arg_terminator_idx, gdb_format_option);
1782 inserted = true;
1783 }
1784
1785 if (!inserted)
1786 revised_command_line.Printf (" %s", gdb_format_option.c_str());
1787
1788 if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
1789 revised_command_line.PutCString (" --");
Greg Clayton52ec56c2011-10-29 00:57:28 +00001790 }
1791 else
1792 {
1793 result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n",
1794 cmd_obj->GetCommandName());
1795 result.SetStatus (eReturnStatusFailed);
1796 return false;
1797 }
1798 }
Greg Clayton5521f992011-10-28 21:38:01 +00001799 break;
Johnny Chen8e9383d2011-10-31 22:22:06 +00001800
1801 default:
1802 result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n",
1803 suffix.c_str());
1804 result.SetStatus (eReturnStatusFailed);
1805 return false;
1806
Greg Clayton5521f992011-10-28 21:38:01 +00001807 }
1808 }
1809 }
Caroline Tice844d2302010-12-09 22:52:49 +00001810 if (command_string.length() == 0)
1811 done = true;
1812
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001813 }
Caroline Tice844d2302010-12-09 22:52:49 +00001814
Greg Clayton5521f992011-10-28 21:38:01 +00001815 if (!command_string.empty())
Caroline Tice844d2302010-12-09 22:52:49 +00001816 revised_command_line.Printf (" %s", command_string.c_str());
1817
1818 // End of Phase 1.
1819 // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
1820 // specified was valid; revised_command_line contains the complete command line (including command name(s)),
1821 // fully translated with all substitutions & translations taken care of (still in raw text format); and
1822 // wants_raw_input specifies whether the Execute method expects raw input or not.
1823
1824
1825 if (log)
1826 {
1827 log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
1828 log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
1829 log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
1830 }
1831
1832 // Phase 2.
1833 // Take care of things like setting up the history command & calling the appropriate Execute method on the
1834 // CommandObject, with the appropriate arguments.
1835
Ed Masted78c9572014-04-20 00:31:37 +00001836 if (cmd_obj != nullptr)
Caroline Tice844d2302010-12-09 22:52:49 +00001837 {
1838 if (add_to_history)
1839 {
1840 Args command_args (revised_command_line.GetData());
1841 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
Ed Masted78c9572014-04-20 00:31:37 +00001842 if (repeat_command != nullptr)
Caroline Tice844d2302010-12-09 22:52:49 +00001843 m_repeat_command.assign(repeat_command);
1844 else
Jim Inghama5a97eb2011-07-12 03:12:18 +00001845 m_repeat_command.assign(original_command_string.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001846
Enrico Granata7594f142013-06-17 22:51:50 +00001847 m_command_history.AppendString (original_command_string);
Caroline Tice844d2302010-12-09 22:52:49 +00001848 }
1849
1850 command_string = revised_command_line.GetData();
1851 std::string command_name (cmd_obj->GetCommandName());
Caroline Tice01274c02010-12-11 08:16:56 +00001852 std::string remainder;
1853 if (actual_cmd_name_len < command_string.length())
1854 remainder = command_string.substr (actual_cmd_name_len); // Note: 'actual_cmd_name_len' may be considerably shorter
1855 // than cmd_obj->GetCommandName(), because name completion
1856 // allows users to enter short versions of the names,
1857 // e.g. 'br s' for 'breakpoint set'.
Caroline Tice844d2302010-12-09 22:52:49 +00001858
1859 // Remove any initial spaces
1860 std::string white_space (" \t\v");
1861 size_t pos = remainder.find_first_not_of (white_space);
1862 if (pos != 0 && pos != std::string::npos)
Greg Claytona3482592011-04-22 20:58:45 +00001863 remainder.erase(0, pos);
Caroline Tice844d2302010-12-09 22:52:49 +00001864
1865 if (log)
Jason Molendabfb36ff2011-08-25 00:20:04 +00001866 log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001867
Jim Ingham5a988412012-06-08 21:56:10 +00001868 cmd_obj->Execute (remainder.c_str(), result);
Caroline Tice844d2302010-12-09 22:52:49 +00001869 }
1870 else
1871 {
1872 // We didn't find the first command object, so complete the first argument.
1873 Args command_args (revised_command_line.GetData());
1874 StringList matches;
1875 int num_matches;
1876 int cursor_index = 0;
1877 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
1878 bool word_complete;
1879 num_matches = HandleCompletionMatches (command_args,
1880 cursor_index,
1881 cursor_char_position,
1882 0,
1883 -1,
1884 word_complete,
1885 matches);
1886
1887 if (num_matches > 0)
1888 {
1889 std::string error_msg;
1890 error_msg.assign ("ambiguous command '");
1891 error_msg.append(command_args.GetArgumentAtIndex(0));
1892 error_msg.append ("'.");
1893
1894 error_msg.append (" Possible completions:");
1895 for (int i = 0; i < num_matches; i++)
1896 {
1897 error_msg.append ("\n\t");
1898 error_msg.append (matches.GetStringAtIndex (i));
1899 }
1900 error_msg.append ("\n");
Greg Claytonc7bece562013-01-25 18:06:21 +00001901 result.AppendRawError (error_msg.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001902 }
1903 else
1904 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
1905
1906 result.SetStatus (eReturnStatusFailed);
1907 }
1908
Jason Molendabfb36ff2011-08-25 00:20:04 +00001909 if (log)
1910 log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
1911
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001912 return result.Succeeded();
1913}
1914
1915int
1916CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
1917 int &cursor_index,
1918 int &cursor_char_position,
1919 int match_start_point,
1920 int max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +00001921 bool &word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001922 StringList &matches)
1923{
1924 int num_command_matches = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001925 bool look_for_subcommand = false;
Jim Ingham558ce122010-06-30 05:02:46 +00001926
1927 // For any of the command completions a unique match will be a complete word.
1928 word_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001929
1930 if (cursor_index == -1)
1931 {
1932 // We got nothing on the command line, so return the list of commands
Jim Ingham279a6c22010-07-06 22:46:59 +00001933 bool include_aliases = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001934 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
1935 }
1936 else if (cursor_index == 0)
1937 {
1938 // The cursor is in the first argument, so just do a lookup in the dictionary.
Jim Ingham279a6c22010-07-06 22:46:59 +00001939 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001940 num_command_matches = matches.GetSize();
1941
1942 if (num_command_matches == 1
1943 && cmd_obj && cmd_obj->IsMultiwordObject()
Ed Masted78c9572014-04-20 00:31:37 +00001944 && matches.GetStringAtIndex(0) != nullptr
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001945 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
1946 {
Greg Clayton765d2e22013-12-10 19:14:04 +00001947 if (parsed_line.GetArgumentCount() == 1)
1948 {
1949 word_complete = true;
1950 }
1951 else
1952 {
1953 look_for_subcommand = true;
1954 num_command_matches = 0;
1955 matches.DeleteStringAtIndex(0);
1956 parsed_line.AppendArgument ("");
1957 cursor_index++;
1958 cursor_char_position = 0;
1959 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001960 }
1961 }
1962
1963 if (cursor_index > 0 || look_for_subcommand)
1964 {
1965 // We are completing further on into a commands arguments, so find the command and tell it
1966 // to complete the command.
1967 // First see if there is a matching initial command:
Jim Ingham279a6c22010-07-06 22:46:59 +00001968 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
Ed Masted78c9572014-04-20 00:31:37 +00001969 if (command_object == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001970 {
1971 return 0;
1972 }
1973 else
1974 {
1975 parsed_line.Shift();
1976 cursor_index--;
Greg Claytona7015092010-09-18 01:14:36 +00001977 num_command_matches = command_object->HandleCompletion (parsed_line,
Greg Clayton66111032010-06-23 01:19:29 +00001978 cursor_index,
1979 cursor_char_position,
1980 match_start_point,
Jim Ingham558ce122010-06-30 05:02:46 +00001981 max_return_elements,
1982 word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001983 matches);
1984 }
1985 }
1986
1987 return num_command_matches;
1988
1989}
1990
1991int
1992CommandInterpreter::HandleCompletion (const char *current_line,
1993 const char *cursor,
1994 const char *last_char,
1995 int match_start_point,
1996 int max_return_elements,
1997 StringList &matches)
1998{
1999 // We parse the argument up to the cursor, so the last argument in parsed_line is
2000 // the one containing the cursor, and the cursor is after the last character.
2001
2002 Args parsed_line(current_line, last_char - current_line);
2003 Args partial_parsed_line(current_line, cursor - current_line);
2004
Jim Inghama5a97eb2011-07-12 03:12:18 +00002005 // Don't complete comments, and if the line we are completing is just the history repeat character,
2006 // substitute the appropriate history line.
2007 const char *first_arg = parsed_line.GetArgumentAtIndex(0);
2008 if (first_arg)
2009 {
2010 if (first_arg[0] == m_comment_char)
2011 return 0;
Enrico Granata7594f142013-06-17 22:51:50 +00002012 else if (first_arg[0] == CommandHistory::g_repeat_char)
Jim Inghama5a97eb2011-07-12 03:12:18 +00002013 {
Enrico Granata7594f142013-06-17 22:51:50 +00002014 const char *history_string = m_command_history.FindString (first_arg);
Ed Masted78c9572014-04-20 00:31:37 +00002015 if (history_string != nullptr)
Jim Inghama5a97eb2011-07-12 03:12:18 +00002016 {
2017 matches.Clear();
2018 matches.InsertStringAtIndex(0, history_string);
2019 return -2;
2020 }
2021 else
2022 return 0;
2023
2024 }
2025 }
2026
2027
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002028 int num_args = partial_parsed_line.GetArgumentCount();
2029 int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
2030 int cursor_char_position;
2031
2032 if (cursor_index == -1)
2033 cursor_char_position = 0;
2034 else
2035 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
Jim Inghamfe0c4252010-12-14 19:56:01 +00002036
2037 if (cursor > current_line && cursor[-1] == ' ')
2038 {
2039 // We are just after a space. If we are in an argument, then we will continue
2040 // parsing, but if we are between arguments, then we have to complete whatever the next
2041 // element would be.
2042 // We can distinguish the two cases because if we are in an argument (e.g. because the space is
2043 // protected by a quote) then the space will also be in the parsed argument...
2044
2045 const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
2046 if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
2047 {
Greg Clayton765d2e22013-12-10 19:14:04 +00002048 parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0');
Jim Inghamfe0c4252010-12-14 19:56:01 +00002049 cursor_index++;
2050 cursor_char_position = 0;
2051 }
2052 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002053
2054 int num_command_matches;
2055
2056 matches.Clear();
2057
2058 // Only max_return_elements == -1 is supported at present:
2059 assert (max_return_elements == -1);
Jim Ingham558ce122010-06-30 05:02:46 +00002060 bool word_complete;
Greg Clayton66111032010-06-23 01:19:29 +00002061 num_command_matches = HandleCompletionMatches (parsed_line,
2062 cursor_index,
2063 cursor_char_position,
2064 match_start_point,
Jim Ingham558ce122010-06-30 05:02:46 +00002065 max_return_elements,
2066 word_complete,
Greg Clayton66111032010-06-23 01:19:29 +00002067 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002068
2069 if (num_command_matches <= 0)
2070 return num_command_matches;
2071
2072 if (num_args == 0)
2073 {
2074 // If we got an empty string, insert nothing.
2075 matches.InsertStringAtIndex(0, "");
2076 }
2077 else
2078 {
2079 // Now figure out if there is a common substring, and if so put that in element 0, otherwise
2080 // put an empty string in element 0.
2081 std::string command_partial_str;
2082 if (cursor_index >= 0)
Jim Ingham49e80a12010-10-22 18:47:16 +00002083 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
2084 parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002085
2086 std::string common_prefix;
2087 matches.LongestCommonPrefix (common_prefix);
Greg Claytonc7bece562013-01-25 18:06:21 +00002088 const size_t partial_name_len = command_partial_str.size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002089
2090 // If we matched a unique single command, add a space...
Jim Ingham558ce122010-06-30 05:02:46 +00002091 // Only do this if the completer told us this was a complete word, however...
2092 if (num_command_matches == 1 && word_complete)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002093 {
2094 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
2095 if (quote_char != '\0')
2096 common_prefix.push_back(quote_char);
2097
2098 common_prefix.push_back(' ');
2099 }
2100 common_prefix.erase (0, partial_name_len);
2101 matches.InsertStringAtIndex(0, common_prefix.c_str());
2102 }
2103 return num_command_matches;
2104}
2105
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002106
2107CommandInterpreter::~CommandInterpreter ()
2108{
2109}
2110
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002111void
Greg Clayton44d93782014-01-27 23:43:24 +00002112CommandInterpreter::UpdatePrompt (const char *new_prompt)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002113{
Greg Clayton44d93782014-01-27 23:43:24 +00002114 EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));;
2115 BroadcastEvent (prompt_change_event_sp);
2116 if (m_command_io_handler_sp)
2117 m_command_io_handler_sp->SetPrompt(new_prompt);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002118}
2119
Jim Ingham97a6dc72010-10-04 19:49:29 +00002120
2121bool
2122CommandInterpreter::Confirm (const char *message, bool default_answer)
2123{
Jim Ingham3bcdb292010-10-04 22:44:14 +00002124 // Check AutoConfirm first:
2125 if (m_debugger.GetAutoConfirm())
2126 return default_answer;
Greg Clayton44d93782014-01-27 23:43:24 +00002127
2128 IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger,
2129 message,
2130 default_answer);
2131 IOHandlerSP io_handler_sp (confirm);
2132 m_debugger.RunIOHandler (io_handler_sp);
2133 return confirm->GetResponse();
Jim Ingham97a6dc72010-10-04 19:49:29 +00002134}
2135
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002136OptionArgVectorSP
2137CommandInterpreter::GetAliasOptions (const char *alias_name)
2138{
2139 OptionArgMap::iterator pos;
2140 OptionArgVectorSP ret_val;
2141
2142 std::string alias (alias_name);
2143
2144 if (HasAliasOptions())
2145 {
2146 pos = m_alias_options.find (alias);
2147 if (pos != m_alias_options.end())
2148 ret_val = pos->second;
2149 }
2150
2151 return ret_val;
2152}
2153
2154void
2155CommandInterpreter::RemoveAliasOptions (const char *alias_name)
2156{
2157 OptionArgMap::iterator pos = m_alias_options.find(alias_name);
2158 if (pos != m_alias_options.end())
2159 {
2160 m_alias_options.erase (pos);
2161 }
2162}
2163
2164void
2165CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
2166{
2167 m_alias_options[alias_name] = option_arg_vector_sp;
2168}
2169
2170bool
2171CommandInterpreter::HasCommands ()
2172{
2173 return (!m_command_dict.empty());
2174}
2175
2176bool
2177CommandInterpreter::HasAliases ()
2178{
2179 return (!m_alias_dict.empty());
2180}
2181
2182bool
2183CommandInterpreter::HasUserCommands ()
2184{
2185 return (!m_user_dict.empty());
2186}
2187
2188bool
2189CommandInterpreter::HasAliasOptions ()
2190{
2191 return (!m_alias_options.empty());
2192}
2193
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002194void
Caroline Tice4ab31c92010-10-12 21:57:09 +00002195CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
2196 const char *alias_name,
2197 Args &cmd_args,
Caroline Ticed9d63362010-12-07 19:58:26 +00002198 std::string &raw_input_string,
Caroline Tice4ab31c92010-10-12 21:57:09 +00002199 CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002200{
2201 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
Caroline Ticed9d63362010-12-07 19:58:26 +00002202
2203 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002204
Caroline Ticed9d63362010-12-07 19:58:26 +00002205 // Make sure that the alias name is the 0th element in cmd_args
2206 std::string alias_name_str = alias_name;
2207 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
2208 cmd_args.Unshift (alias_name);
2209
2210 Args new_args (alias_cmd_obj->GetCommandName());
2211 if (new_args.GetArgumentCount() == 2)
2212 new_args.Shift();
2213
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002214 if (option_arg_vector_sp.get())
2215 {
Caroline Ticed9d63362010-12-07 19:58:26 +00002216 if (wants_raw_input)
2217 {
2218 // We have a command that both has command options and takes raw input. Make *sure* it has a
2219 // " -- " in the right place in the raw_input_string.
2220 size_t pos = raw_input_string.find(" -- ");
2221 if (pos == std::string::npos)
2222 {
2223 // None found; assume it goes at the beginning of the raw input string
2224 raw_input_string.insert (0, " -- ");
2225 }
2226 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002227
2228 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
Greg Claytonc7bece562013-01-25 18:06:21 +00002229 const size_t old_size = cmd_args.GetArgumentCount();
Caroline Tice4ab31c92010-10-12 21:57:09 +00002230 std::vector<bool> used (old_size + 1, false);
2231
2232 used[0] = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002233
Andy Gibbsa297a972013-06-19 19:04:53 +00002234 for (size_t i = 0; i < option_arg_vector->size(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002235 {
2236 OptionArgPair option_pair = (*option_arg_vector)[i];
Caroline Ticed9d63362010-12-07 19:58:26 +00002237 OptionArgValue value_pair = option_pair.second;
2238 int value_type = value_pair.first;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002239 std::string option = option_pair.first;
Caroline Ticed9d63362010-12-07 19:58:26 +00002240 std::string value = value_pair.second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002241 if (option.compare ("<argument>") == 0)
Caroline Ticed9d63362010-12-07 19:58:26 +00002242 {
2243 if (!wants_raw_input
2244 || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
2245 new_args.AppendArgument (value.c_str());
2246 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002247 else
2248 {
Virgile Belloe2607b52013-09-05 16:42:23 +00002249 if (value_type != OptionParser::eOptionalArgument)
Caroline Ticed9d63362010-12-07 19:58:26 +00002250 new_args.AppendArgument (option.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002251 if (value.compare ("<no-argument>") != 0)
2252 {
2253 int index = GetOptionArgumentPosition (value.c_str());
2254 if (index == 0)
Caroline Ticed9d63362010-12-07 19:58:26 +00002255 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002256 // value was NOT a positional argument; must be a real value
Virgile Belloe2607b52013-09-05 16:42:23 +00002257 if (value_type != OptionParser::eOptionalArgument)
Caroline Ticed9d63362010-12-07 19:58:26 +00002258 new_args.AppendArgument (value.c_str());
2259 else
2260 {
2261 char buffer[255];
2262 ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
2263 new_args.AppendArgument (buffer);
2264 }
2265
2266 }
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +00002267 else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002268 {
2269 result.AppendErrorWithFormat
2270 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
2271 index);
2272 result.SetStatus (eReturnStatusFailed);
2273 return;
2274 }
2275 else
2276 {
Caroline Ticed9d63362010-12-07 19:58:26 +00002277 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2278 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
2279 if (strpos != std::string::npos)
2280 {
2281 raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
2282 }
2283
Virgile Belloe2607b52013-09-05 16:42:23 +00002284 if (value_type != OptionParser::eOptionalArgument)
Caroline Ticed9d63362010-12-07 19:58:26 +00002285 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
2286 else
2287 {
2288 char buffer[255];
2289 ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
2290 cmd_args.GetArgumentAtIndex (index));
2291 new_args.AppendArgument (buffer);
2292 }
Caroline Tice4ab31c92010-10-12 21:57:09 +00002293 used[index] = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002294 }
2295 }
2296 }
2297 }
2298
Andy Gibbsa297a972013-06-19 19:04:53 +00002299 for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002300 {
Caroline Ticed9d63362010-12-07 19:58:26 +00002301 if (!used[j] && !wants_raw_input)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002302 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
2303 }
2304
2305 cmd_args.Clear();
2306 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2307 }
2308 else
2309 {
2310 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Caroline Ticed9d63362010-12-07 19:58:26 +00002311 // This alias was not created with any options; nothing further needs to be done, unless it is a command that
2312 // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
2313 // input string.
2314 if (wants_raw_input)
2315 {
2316 cmd_args.Clear();
2317 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2318 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002319 return;
2320 }
2321
2322 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2323 return;
2324}
2325
2326
2327int
2328CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
2329{
2330 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
2331 // of zero.
2332
2333 char *cptr = (char *) in_string;
2334
2335 // Does it start with '%'
2336 if (cptr[0] == '%')
2337 {
2338 ++cptr;
2339
2340 // Is the rest of it entirely digits?
2341 if (isdigit (cptr[0]))
2342 {
2343 const char *start = cptr;
2344 while (isdigit (cptr[0]))
2345 ++cptr;
2346
2347 // We've gotten to the end of the digits; are we at the end of the string?
2348 if (cptr[0] == '\0')
2349 position = atoi (start);
2350 }
2351 }
2352
2353 return position;
2354}
2355
2356void
2357CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
2358{
Jim Ingham16e0c682011-08-12 23:34:31 +00002359 FileSpec init_file;
Greg Clayton14a35512011-09-11 00:01:44 +00002360 if (in_cwd)
Jim Ingham16e0c682011-08-12 23:34:31 +00002361 {
Greg Clayton14a35512011-09-11 00:01:44 +00002362 // In the current working directory we don't load any program specific
2363 // .lldbinit files, we only look for a "./.lldbinit" file.
2364 if (m_skip_lldbinit_files)
2365 return;
2366
2367 init_file.SetFile ("./.lldbinit", true);
Jim Ingham16e0c682011-08-12 23:34:31 +00002368 }
Greg Clayton14a35512011-09-11 00:01:44 +00002369 else
Jim Ingham16e0c682011-08-12 23:34:31 +00002370 {
Greg Clayton14a35512011-09-11 00:01:44 +00002371 // If we aren't looking in the current working directory we are looking
2372 // in the home directory. We will first see if there is an application
2373 // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
2374 // "-" and the name of the program. If this file doesn't exist, we fall
2375 // back to just the "~/.lldbinit" file. We also obey any requests to not
2376 // load the init files.
2377 const char *init_file_path = "~/.lldbinit";
2378
2379 if (m_skip_app_init_files == false)
2380 {
2381 FileSpec program_file_spec (Host::GetProgramFileSpec());
2382 const char *program_name = program_file_spec.GetFilename().AsCString();
Jim Ingham16e0c682011-08-12 23:34:31 +00002383
Greg Clayton14a35512011-09-11 00:01:44 +00002384 if (program_name)
2385 {
2386 char program_init_file_name[PATH_MAX];
2387 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name);
2388 init_file.SetFile (program_init_file_name, true);
2389 if (!init_file.Exists())
2390 init_file.Clear();
2391 }
2392 }
2393
2394 if (!init_file && !m_skip_lldbinit_files)
2395 init_file.SetFile (init_file_path, true);
2396 }
2397
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002398 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
2399 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
2400
2401 if (init_file.Exists())
2402 {
Greg Clayton44d93782014-01-27 23:43:24 +00002403 const bool saved_batch = SetBatchCommandMode (true);
Greg Clayton340b0302014-02-05 17:57:57 +00002404 HandleCommandsFromFile (init_file,
Ed Masted78c9572014-04-20 00:31:37 +00002405 nullptr, // Execution context
Greg Clayton340b0302014-02-05 17:57:57 +00002406 eLazyBoolYes, // Stop on continue
2407 eLazyBoolNo, // Stop on error
2408 eLazyBoolNo, // Don't echo commands
2409 eLazyBoolNo, // Don't print command output
2410 eLazyBoolNo, // Don't add the commands that are sourced into the history buffer
2411 result);
Greg Clayton44d93782014-01-27 23:43:24 +00002412 SetBatchCommandMode (saved_batch);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002413 }
2414 else
2415 {
2416 // nothing to be done if the file doesn't exist
2417 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2418 }
2419}
2420
Greg Clayton8b82f082011-04-12 05:54:46 +00002421PlatformSP
2422CommandInterpreter::GetPlatform (bool prefer_target_platform)
2423{
2424 PlatformSP platform_sp;
Greg Claytonc14ee322011-09-22 04:58:26 +00002425 if (prefer_target_platform)
2426 {
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00002427 ExecutionContext exe_ctx(GetExecutionContext());
2428 Target *target = exe_ctx.GetTargetPtr();
Greg Claytonc14ee322011-09-22 04:58:26 +00002429 if (target)
2430 platform_sp = target->GetPlatform();
2431 }
Greg Clayton8b82f082011-04-12 05:54:46 +00002432
2433 if (!platform_sp)
2434 platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
2435 return platform_sp;
2436}
2437
Jim Inghame16c50a2011-02-18 00:54:25 +00002438void
Jim Inghambad87fe2011-03-11 01:51:49 +00002439CommandInterpreter::HandleCommands (const StringList &commands,
Jim Inghame16c50a2011-02-18 00:54:25 +00002440 ExecutionContext *override_context,
2441 bool stop_on_continue,
2442 bool stop_on_error,
2443 bool echo_commands,
2444 bool print_results,
Enrico Granata5f5ab602012-05-31 01:09:06 +00002445 LazyBool add_to_history,
Jim Inghame16c50a2011-02-18 00:54:25 +00002446 CommandReturnObject &result)
2447{
2448 size_t num_lines = commands.GetSize();
Jim Inghame16c50a2011-02-18 00:54:25 +00002449
2450 // If we are going to continue past a "continue" then we need to run the commands synchronously.
2451 // Make sure you reset this value anywhere you return from the function.
2452
2453 bool old_async_execution = m_debugger.GetAsyncExecution();
2454
2455 // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
2456 // cause series of commands that change the context, then do an operation that relies on that context to fail.
2457
Ed Masted78c9572014-04-20 00:31:37 +00002458 if (override_context != nullptr)
Greg Clayton8b82f082011-04-12 05:54:46 +00002459 UpdateExecutionContext (override_context);
Jim Inghame16c50a2011-02-18 00:54:25 +00002460
2461 if (!stop_on_continue)
2462 {
2463 m_debugger.SetAsyncExecution (false);
2464 }
2465
Andy Gibbsa297a972013-06-19 19:04:53 +00002466 for (size_t idx = 0; idx < num_lines; idx++)
Jim Inghame16c50a2011-02-18 00:54:25 +00002467 {
2468 const char *cmd = commands.GetStringAtIndex(idx);
2469 if (cmd[0] == '\0')
2470 continue;
2471
Jim Inghame16c50a2011-02-18 00:54:25 +00002472 if (echo_commands)
2473 {
2474 result.AppendMessageWithFormat ("%s %s\n",
Greg Clayton44d93782014-01-27 23:43:24 +00002475 m_debugger.GetPrompt(),
2476 cmd);
Jim Inghame16c50a2011-02-18 00:54:25 +00002477 }
2478
Greg Clayton9d0402b2011-02-20 02:15:07 +00002479 CommandReturnObject tmp_result;
Johnny Chen80fdd7c2011-10-05 00:42:59 +00002480 // If override_context is not NULL, pass no_context_switching = true for
2481 // HandleCommand() since we updated our context already.
Jim Ingham076b7fc2013-05-02 23:15:37 +00002482
2483 // We might call into a regex or alias command, in which case the add_to_history will get lost. This
2484 // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
2485 if (!add_to_history)
2486 m_command_source_depth++;
Enrico Granata5f5ab602012-05-31 01:09:06 +00002487 bool success = HandleCommand(cmd, add_to_history, tmp_result,
Ed Masted78c9572014-04-20 00:31:37 +00002488 nullptr, /* override_context */
Johnny Chen80fdd7c2011-10-05 00:42:59 +00002489 true, /* repeat_on_empty_command */
Ed Masted78c9572014-04-20 00:31:37 +00002490 override_context != nullptr /* no_context_switching */);
Jim Ingham076b7fc2013-05-02 23:15:37 +00002491 if (!add_to_history)
2492 m_command_source_depth--;
Jim Inghame16c50a2011-02-18 00:54:25 +00002493
2494 if (print_results)
2495 {
2496 if (tmp_result.Succeeded())
Jim Ingham85e8b812011-02-19 02:53:09 +00002497 result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
Jim Inghame16c50a2011-02-18 00:54:25 +00002498 }
2499
2500 if (!success || !tmp_result.Succeeded())
2501 {
Jim Inghama5038812012-04-24 02:25:07 +00002502 const char *error_msg = tmp_result.GetErrorData();
Ed Masted78c9572014-04-20 00:31:37 +00002503 if (error_msg == nullptr || error_msg[0] == '\0')
Jim Inghama5038812012-04-24 02:25:07 +00002504 error_msg = "<unknown error>.\n";
Jim Inghame16c50a2011-02-18 00:54:25 +00002505 if (stop_on_error)
2506 {
Deepak Panickal99fbc072014-03-03 15:39:47 +00002507 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s",
2508 (uint64_t)idx, cmd, error_msg);
Jim Inghame16c50a2011-02-18 00:54:25 +00002509 result.SetStatus (eReturnStatusFailed);
2510 m_debugger.SetAsyncExecution (old_async_execution);
2511 return;
2512 }
2513 else if (print_results)
2514 {
Deepak Panickal99fbc072014-03-03 15:39:47 +00002515 result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s",
2516 (uint64_t)idx + 1,
Jim Inghame16c50a2011-02-18 00:54:25 +00002517 cmd,
Jim Inghama5038812012-04-24 02:25:07 +00002518 error_msg);
Jim Inghame16c50a2011-02-18 00:54:25 +00002519 }
2520 }
2521
Caroline Tice969ed3d2011-05-02 20:41:46 +00002522 if (result.GetImmediateOutputStream())
2523 result.GetImmediateOutputStream()->Flush();
2524
2525 if (result.GetImmediateErrorStream())
2526 result.GetImmediateErrorStream()->Flush();
2527
Jim Inghame16c50a2011-02-18 00:54:25 +00002528 // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
2529 // could be running (for instance in Breakpoint Commands.
2530 // So we check the return value to see if it is has running in it.
2531 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
2532 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
2533 {
2534 if (stop_on_continue)
2535 {
2536 // If we caused the target to proceed, and we're going to stop in that case, set the
2537 // status in our real result before returning. This is an error if the continue was not the
2538 // last command in the set of commands to be run.
2539 if (idx != num_lines - 1)
Deepak Panickal99fbc072014-03-03 15:39:47 +00002540 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' continued the target.\n",
2541 (uint64_t)idx + 1, cmd);
Jim Inghame16c50a2011-02-18 00:54:25 +00002542 else
Deepak Panickal99fbc072014-03-03 15:39:47 +00002543 result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' continued the target.\n", (uint64_t)idx + 1, cmd);
Jim Inghame16c50a2011-02-18 00:54:25 +00002544
2545 result.SetStatus(tmp_result.GetStatus());
2546 m_debugger.SetAsyncExecution (old_async_execution);
2547
2548 return;
2549 }
2550 }
2551
2552 }
2553
2554 result.SetStatus (eReturnStatusSuccessFinishResult);
2555 m_debugger.SetAsyncExecution (old_async_execution);
2556
2557 return;
2558}
2559
Greg Clayton340b0302014-02-05 17:57:57 +00002560// Make flags that we can pass into the IOHandler so our delegates can do the right thing
2561enum {
2562 eHandleCommandFlagStopOnContinue = (1u << 0),
2563 eHandleCommandFlagStopOnError = (1u << 1),
2564 eHandleCommandFlagEchoCommand = (1u << 2),
2565 eHandleCommandFlagPrintResult = (1u << 3)
2566};
2567
Jim Inghame16c50a2011-02-18 00:54:25 +00002568void
2569CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
2570 ExecutionContext *context,
Greg Clayton340b0302014-02-05 17:57:57 +00002571 LazyBool stop_on_continue,
2572 LazyBool stop_on_error,
2573 LazyBool echo_command,
2574 LazyBool print_result,
Enrico Granata5f5ab602012-05-31 01:09:06 +00002575 LazyBool add_to_history,
Jim Inghame16c50a2011-02-18 00:54:25 +00002576 CommandReturnObject &result)
2577{
2578 if (cmd_file.Exists())
2579 {
Greg Clayton44d93782014-01-27 23:43:24 +00002580 StreamFileSP input_file_sp (new StreamFile());
2581
2582 std::string cmd_file_path = cmd_file.GetPath();
2583 Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead);
2584
2585 if (error.Success())
2586 {
2587 Debugger &debugger = GetDebugger();
2588
Greg Clayton340b0302014-02-05 17:57:57 +00002589 uint32_t flags = 0;
2590
2591 if (stop_on_continue == eLazyBoolCalculate)
2592 {
2593 if (m_command_source_flags.empty())
2594 {
Greg Claytone4e462c2014-02-05 21:03:22 +00002595 // Stop on continue by default
Greg Clayton340b0302014-02-05 17:57:57 +00002596 flags |= eHandleCommandFlagStopOnContinue;
2597 }
2598 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue)
2599 {
2600 flags |= eHandleCommandFlagStopOnContinue;
2601 }
2602 }
2603 else if (stop_on_continue == eLazyBoolYes)
2604 {
2605 flags |= eHandleCommandFlagStopOnContinue;
2606 }
2607
2608 if (stop_on_error == eLazyBoolCalculate)
2609 {
2610 if (m_command_source_flags.empty())
2611 {
2612 if (GetStopCmdSourceOnError())
2613 flags |= eHandleCommandFlagStopOnError;
2614 }
2615 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError)
2616 {
2617 flags |= eHandleCommandFlagStopOnError;
2618 }
2619 }
2620 else if (stop_on_error == eLazyBoolYes)
2621 {
2622 flags |= eHandleCommandFlagStopOnError;
2623 }
2624
2625 if (echo_command == eLazyBoolCalculate)
2626 {
2627 if (m_command_source_flags.empty())
2628 {
2629 // Echo command by default
2630 flags |= eHandleCommandFlagEchoCommand;
2631 }
2632 else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand)
2633 {
2634 flags |= eHandleCommandFlagEchoCommand;
2635 }
2636 }
2637 else if (echo_command == eLazyBoolYes)
2638 {
2639 flags |= eHandleCommandFlagEchoCommand;
2640 }
2641
2642 if (print_result == eLazyBoolCalculate)
2643 {
2644 if (m_command_source_flags.empty())
2645 {
Greg Claytone4e462c2014-02-05 21:03:22 +00002646 // Print output by default
2647 flags |= eHandleCommandFlagPrintResult;
Greg Clayton340b0302014-02-05 17:57:57 +00002648 }
Greg Claytone4e462c2014-02-05 21:03:22 +00002649 else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult)
Greg Clayton340b0302014-02-05 17:57:57 +00002650 {
Greg Claytone4e462c2014-02-05 21:03:22 +00002651 flags |= eHandleCommandFlagPrintResult;
Greg Clayton340b0302014-02-05 17:57:57 +00002652 }
2653 }
2654 else if (print_result == eLazyBoolYes)
2655 {
Greg Claytone4e462c2014-02-05 21:03:22 +00002656 flags |= eHandleCommandFlagPrintResult;
2657 }
2658
2659 if (flags & eHandleCommandFlagPrintResult)
2660 {
Greg Clayton8ee67312014-02-05 21:46:20 +00002661 debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str());
Greg Clayton340b0302014-02-05 17:57:57 +00002662 }
2663
2664 // Used for inheriting the right settings when "command source" might have
2665 // nested "command source" commands
Greg Claytone4e462c2014-02-05 21:03:22 +00002666 lldb::StreamFileSP empty_stream_sp;
Greg Clayton340b0302014-02-05 17:57:57 +00002667 m_command_source_flags.push_back(flags);
Greg Clayton44d93782014-01-27 23:43:24 +00002668 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
2669 input_file_sp,
Greg Claytone4e462c2014-02-05 21:03:22 +00002670 empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream
2671 empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream
Greg Clayton340b0302014-02-05 17:57:57 +00002672 flags,
Ed Masted78c9572014-04-20 00:31:37 +00002673 nullptr, // Pass in NULL for "editline_name" so no history is saved, or written
Greg Clayton8ee67312014-02-05 21:46:20 +00002674 debugger.GetPrompt(),
Greg Clayton44d93782014-01-27 23:43:24 +00002675 false, // Not multi-line
Greg Claytonf6913cd2014-03-07 00:53:24 +00002676 0,
Greg Clayton44d93782014-01-27 23:43:24 +00002677 *this));
Greg Clayton8ee67312014-02-05 21:46:20 +00002678 const bool old_async_execution = debugger.GetAsyncExecution();
2679
2680 // Set synchronous execution if we not stopping when we continue
2681 if ((flags & eHandleCommandFlagStopOnContinue) == 0)
2682 debugger.SetAsyncExecution (false);
2683
Greg Clayton340b0302014-02-05 17:57:57 +00002684 m_command_source_depth++;
Greg Clayton8ee67312014-02-05 21:46:20 +00002685
2686 debugger.RunIOHandler(io_handler_sp);
Greg Clayton340b0302014-02-05 17:57:57 +00002687 if (!m_command_source_flags.empty())
2688 m_command_source_flags.pop_back();
2689 m_command_source_depth--;
Greg Clayton44d93782014-01-27 23:43:24 +00002690 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton8ee67312014-02-05 21:46:20 +00002691 debugger.SetAsyncExecution (old_async_execution);
Greg Clayton44d93782014-01-27 23:43:24 +00002692 }
2693 else
2694 {
2695 result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString());
2696 result.SetStatus (eReturnStatusFailed);
2697 }
Greg Clayton8ee67312014-02-05 21:46:20 +00002698
2699
Jim Inghame16c50a2011-02-18 00:54:25 +00002700 }
2701 else
2702 {
2703 result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
2704 cmd_file.GetFilename().AsCString());
2705 result.SetStatus (eReturnStatusFailed);
2706 return;
2707 }
2708}
2709
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002710ScriptInterpreter *
Enrico Granatab5887262012-10-29 21:18:03 +00002711CommandInterpreter::GetScriptInterpreter (bool can_create)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002712{
Ed Masted78c9572014-04-20 00:31:37 +00002713 if (m_script_interpreter_ap.get() != nullptr)
Enrico Granatab5887262012-10-29 21:18:03 +00002714 return m_script_interpreter_ap.get();
2715
2716 if (!can_create)
Ed Masted78c9572014-04-20 00:31:37 +00002717 return nullptr;
Enrico Granatab5887262012-10-29 21:18:03 +00002718
Enrico Granataa29bdad2012-07-10 18:23:48 +00002719 // <rdar://problem/11751427>
2720 // we need to protect the initialization of the script interpreter
2721 // otherwise we could end up with two threads both trying to create
2722 // their instance of it, and for some languages (e.g. Python)
2723 // this is a bulletproof recipe for disaster!
2724 // this needs to be a function-level static because multiple Debugger instances living in the same process
2725 // still need to be isolated and not try to initialize Python concurrently
Enrico Granata8b95df22012-07-10 19:04:14 +00002726 static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
2727 Mutex::Locker interpreter_lock(g_interpreter_mutex);
Enrico Granataa29bdad2012-07-10 18:23:48 +00002728
Greg Clayton5160ce52013-03-27 23:08:40 +00002729 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Enrico Granatab5887262012-10-29 21:18:03 +00002730 if (log)
2731 log->Printf("Initializing the ScriptInterpreter now\n");
Greg Clayton66111032010-06-23 01:19:29 +00002732
Caroline Tice2f88aad2011-01-14 00:29:16 +00002733 lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
2734 switch (script_lang)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002735 {
Greg Claytondce502e2011-11-04 03:34:56 +00002736 case eScriptLanguagePython:
2737#ifndef LLDB_DISABLE_PYTHON
2738 m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
2739 break;
2740#else
2741 // Fall through to the None case when python is disabled
2742#endif
Caroline Tice2f88aad2011-01-14 00:29:16 +00002743 case eScriptLanguageNone:
2744 m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
2745 break;
Caroline Tice2f88aad2011-01-14 00:29:16 +00002746 };
2747
2748 return m_script_interpreter_ap.get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002749}
2750
2751
2752
2753bool
2754CommandInterpreter::GetSynchronous ()
2755{
2756 return m_synchronous_execution;
2757}
2758
2759void
2760CommandInterpreter::SetSynchronous (bool value)
2761{
Johnny Chenc066ab42010-10-14 01:22:03 +00002762 m_synchronous_execution = value;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002763}
2764
2765void
2766CommandInterpreter::OutputFormattedHelpText (Stream &strm,
2767 const char *word_text,
2768 const char *separator,
2769 const char *help_text,
Greg Claytonc7bece562013-01-25 18:06:21 +00002770 size_t max_word_len)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002771{
Greg Claytona7015092010-09-18 01:14:36 +00002772 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2773
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002774 int indent_size = max_word_len + strlen (separator) + 2;
2775
2776 strm.IndentMore (indent_size);
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002777
2778 StreamString text_strm;
Greg Claytonc7bece562013-01-25 18:06:21 +00002779 text_strm.Printf ("%-*s %s %s", (int)max_word_len, word_text, separator, help_text);
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002780
2781 size_t len = text_strm.GetSize();
2782 const char *text = text_strm.GetData();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002783 if (text[len - 1] == '\n')
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002784 {
2785 text_strm.EOL();
2786 len = text_strm.GetSize();
2787 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002788
2789 if (len < max_columns)
2790 {
2791 // Output it as a single line.
2792 strm.Printf ("%s", text);
2793 }
2794 else
2795 {
2796 // We need to break it up into multiple lines.
2797 bool first_line = true;
2798 int text_width;
Greg Claytonc7bece562013-01-25 18:06:21 +00002799 size_t start = 0;
2800 size_t end = start;
2801 const size_t final_end = strlen (text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002802
2803 while (end < final_end)
2804 {
2805 if (first_line)
2806 text_width = max_columns - 1;
2807 else
2808 text_width = max_columns - indent_size - 1;
2809
2810 // Don't start the 'text' on a space, since we're already outputting the indentation.
2811 if (!first_line)
2812 {
2813 while ((start < final_end) && (text[start] == ' '))
2814 start++;
2815 }
2816
2817 end = start + text_width;
2818 if (end > final_end)
2819 end = final_end;
2820 else
2821 {
2822 // If we're not at the end of the text, make sure we break the line on white space.
2823 while (end > start
2824 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
2825 end--;
Greg Clayton67cc0632012-08-22 17:17:09 +00002826 assert (end > 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002827 }
2828
Greg Claytonc7bece562013-01-25 18:06:21 +00002829 const size_t sub_len = end - start;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002830 if (start != 0)
2831 strm.EOL();
2832 if (!first_line)
2833 strm.Indent();
2834 else
2835 first_line = false;
2836 assert (start <= final_end);
2837 assert (start + sub_len <= final_end);
2838 if (sub_len > 0)
2839 strm.Write (text + start, sub_len);
2840 start = end + 1;
2841 }
2842 }
2843 strm.EOL();
2844 strm.IndentLess(indent_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002845}
2846
2847void
Enrico Granata82a7d982011-07-07 00:38:40 +00002848CommandInterpreter::OutputHelpText (Stream &strm,
2849 const char *word_text,
2850 const char *separator,
2851 const char *help_text,
2852 uint32_t max_word_len)
2853{
2854 int indent_size = max_word_len + strlen (separator) + 2;
2855
2856 strm.IndentMore (indent_size);
2857
2858 StreamString text_strm;
2859 text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
2860
2861 const uint32_t max_columns = m_debugger.GetTerminalWidth();
Enrico Granata82a7d982011-07-07 00:38:40 +00002862
2863 size_t len = text_strm.GetSize();
2864 const char *text = text_strm.GetData();
2865
2866 uint32_t chars_left = max_columns;
2867
2868 for (uint32_t i = 0; i < len; i++)
2869 {
2870 if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
2871 {
Enrico Granata82a7d982011-07-07 00:38:40 +00002872 chars_left = max_columns - indent_size;
2873 strm.EOL();
2874 strm.Indent();
2875 }
2876 else
2877 {
2878 strm.PutChar(text[i]);
2879 chars_left--;
2880 }
2881
2882 }
2883
2884 strm.EOL();
2885 strm.IndentLess(indent_size);
2886}
2887
2888void
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002889CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
Jim Inghamaf3753e2013-05-17 01:30:37 +00002890 StringList &commands_help, bool search_builtin_commands, bool search_user_commands)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002891{
2892 CommandObject::CommandMap::const_iterator pos;
2893
Jim Inghamaf3753e2013-05-17 01:30:37 +00002894 if (search_builtin_commands)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002895 {
Jim Inghamaf3753e2013-05-17 01:30:37 +00002896 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002897 {
Jim Inghamaf3753e2013-05-17 01:30:37 +00002898 const char *command_name = pos->first.c_str();
2899 CommandObject *cmd_obj = pos->second.get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002900
Jim Inghamaf3753e2013-05-17 01:30:37 +00002901 if (cmd_obj->HelpTextContainsWord (search_word))
2902 {
2903 commands_found.AppendString (command_name);
2904 commands_help.AppendString (cmd_obj->GetHelp());
2905 }
2906
2907 if (cmd_obj->IsMultiwordObject())
2908 cmd_obj->AproposAllSubCommands (command_name,
2909 search_word,
2910 commands_found,
2911 commands_help);
2912
2913 }
2914 }
2915
2916 if (search_user_commands)
2917 {
2918 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
2919 {
2920 const char *command_name = pos->first.c_str();
2921 CommandObject *cmd_obj = pos->second.get();
2922
2923 if (cmd_obj->HelpTextContainsWord (search_word))
2924 {
2925 commands_found.AppendString (command_name);
2926 commands_help.AppendString (cmd_obj->GetHelp());
2927 }
2928
2929 if (cmd_obj->IsMultiwordObject())
2930 cmd_obj->AproposAllSubCommands (command_name,
2931 search_word,
2932 commands_found,
2933 commands_help);
2934
2935 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002936 }
2937}
Greg Clayton8b82f082011-04-12 05:54:46 +00002938
Greg Clayton8b82f082011-04-12 05:54:46 +00002939void
2940CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
2941{
Ed Masted78c9572014-04-20 00:31:37 +00002942 if (override_context != nullptr)
Greg Clayton8b82f082011-04-12 05:54:46 +00002943 {
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00002944 m_exe_ctx_ref = *override_context;
Greg Clayton8b82f082011-04-12 05:54:46 +00002945 }
2946 else
2947 {
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00002948 const bool adopt_selected = true;
2949 m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
Greg Clayton8b82f082011-04-12 05:54:46 +00002950 }
2951}
Greg Clayton44d93782014-01-27 23:43:24 +00002952
2953
2954size_t
2955CommandInterpreter::GetProcessOutput ()
2956{
2957 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
2958 char stdio_buffer[1024];
2959 size_t len;
2960 size_t total_bytes = 0;
2961 Error error;
2962 TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
2963 if (target_sp)
2964 {
2965 ProcessSP process_sp (target_sp->GetProcessSP());
2966 if (process_sp)
2967 {
2968 while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
2969 {
2970 size_t bytes_written = len;
2971 m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written);
2972 total_bytes += len;
2973 }
2974 while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
2975 {
2976 size_t bytes_written = len;
2977 m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written);
2978 total_bytes += len;
2979 }
2980 }
2981 }
2982 return total_bytes;
2983}
2984
2985void
2986CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
2987{
Greg Clayton340b0302014-02-05 17:57:57 +00002988 const bool is_interactive = io_handler.GetIsInteractive();
2989 if (is_interactive == false)
2990 {
2991 // When we are not interactive, don't execute blank lines. This will happen
2992 // sourcing a commands file. We don't want blank lines to repeat the previous
2993 // command and cause any errors to occur (like redefining an alias, get an error
2994 // and stop parsing the commands file).
2995 if (line.empty())
2996 return;
2997
2998 // When using a non-interactive file handle (like when sourcing commands from a file)
2999 // we need to echo the command out so we don't just see the command output and no
3000 // command...
3001 if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
3002 io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
3003 }
3004
Greg Clayton44d93782014-01-27 23:43:24 +00003005 lldb_private::CommandReturnObject result;
3006 HandleCommand(line.c_str(), eLazyBoolCalculate, result);
3007
Greg Clayton44d93782014-01-27 23:43:24 +00003008 // Now emit the command output text from the command we just executed
Greg Clayton340b0302014-02-05 17:57:57 +00003009 if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult))
3010 {
3011 // Display any STDOUT/STDERR _prior_ to emitting the command result text
3012 GetProcessOutput ();
3013
Greg Clayton8ee67312014-02-05 21:46:20 +00003014 if (!result.GetImmediateOutputStream())
3015 {
3016 const char *output = result.GetOutputData();
3017 if (output && output[0])
3018 io_handler.GetOutputStreamFile()->PutCString(output);
3019 }
Greg Clayton44d93782014-01-27 23:43:24 +00003020
Greg Clayton340b0302014-02-05 17:57:57 +00003021 // Now emit the command error text from the command we just executed
Greg Clayton8ee67312014-02-05 21:46:20 +00003022 if (!result.GetImmediateErrorStream())
3023 {
3024 const char *error = result.GetErrorData();
3025 if (error && error[0])
3026 io_handler.GetErrorStreamFile()->PutCString(error);
3027 }
Greg Clayton340b0302014-02-05 17:57:57 +00003028 }
Greg Clayton44d93782014-01-27 23:43:24 +00003029
3030 switch (result.GetStatus())
3031 {
3032 case eReturnStatusInvalid:
3033 case eReturnStatusSuccessFinishNoResult:
3034 case eReturnStatusSuccessFinishResult:
Greg Clayton340b0302014-02-05 17:57:57 +00003035 case eReturnStatusStarted:
3036 break;
3037
Greg Clayton44d93782014-01-27 23:43:24 +00003038 case eReturnStatusSuccessContinuingNoResult:
3039 case eReturnStatusSuccessContinuingResult:
Greg Clayton340b0302014-02-05 17:57:57 +00003040 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue))
3041 io_handler.SetIsDone(true);
3042 break;
3043
Greg Clayton44d93782014-01-27 23:43:24 +00003044 case eReturnStatusFailed:
Greg Clayton340b0302014-02-05 17:57:57 +00003045 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError))
3046 io_handler.SetIsDone(true);
Greg Clayton44d93782014-01-27 23:43:24 +00003047 break;
3048
3049 case eReturnStatusQuit:
3050 io_handler.SetIsDone(true);
3051 break;
3052 }
3053}
3054
Greg Claytonf0066ad2014-05-02 00:45:31 +00003055bool
3056CommandInterpreter::IOHandlerInterrupt (IOHandler &io_handler)
3057{
3058 ExecutionContext exe_ctx (GetExecutionContext());
3059 Process *process = exe_ctx.GetProcessPtr();
3060
3061 if (process)
3062 {
3063 StateType state = process->GetState();
3064 if (StateIsRunningState(state))
3065 {
3066 process->Halt();
3067 return true; // Don't do any updating when we are running
3068 }
3069 }
3070 return false;
3071}
3072
Greg Clayton44d93782014-01-27 23:43:24 +00003073void
3074CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,
3075 IOHandlerDelegate &delegate,
3076 bool asynchronously,
3077 void *baton)
3078{
3079 Debugger &debugger = GetDebugger();
3080 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
3081 "lldb", // Name of input reader for history
3082 prompt, // Prompt
3083 true, // Get multiple lines
Greg Claytonf6913cd2014-03-07 00:53:24 +00003084 0, // Don't show line numbers
Greg Clayton44d93782014-01-27 23:43:24 +00003085 delegate)); // IOHandlerDelegate
3086
3087 if (io_handler_sp)
3088 {
3089 io_handler_sp->SetUserData (baton);
3090 if (asynchronously)
3091 debugger.PushIOHandler(io_handler_sp);
3092 else
3093 debugger.RunIOHandler(io_handler_sp);
3094 }
3095
3096}
3097
3098
3099void
3100CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt,
3101 IOHandlerDelegate &delegate,
3102 bool asynchronously,
3103 void *baton)
3104{
3105 Debugger &debugger = GetDebugger();
3106 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
3107 "lldb-python", // Name of input reader for history
3108 prompt, // Prompt
3109 true, // Get multiple lines
Greg Claytonf6913cd2014-03-07 00:53:24 +00003110 0, // Don't show line numbers
Greg Clayton44d93782014-01-27 23:43:24 +00003111 delegate)); // IOHandlerDelegate
3112
3113 if (io_handler_sp)
3114 {
3115 io_handler_sp->SetUserData (baton);
3116 if (asynchronously)
3117 debugger.PushIOHandler(io_handler_sp);
3118 else
3119 debugger.RunIOHandler(io_handler_sp);
3120 }
3121
3122}
3123
3124bool
3125CommandInterpreter::IsActive ()
3126{
3127 return m_debugger.IsTopIOHandler (m_command_io_handler_sp);
3128}
3129
3130void
3131CommandInterpreter::RunCommandInterpreter(bool auto_handle_events,
3132 bool spawn_thread)
3133{
3134 const bool multiple_lines = false; // Only get one line at a time
3135 if (!m_command_io_handler_sp)
3136 m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger,
3137 m_debugger.GetInputFile(),
3138 m_debugger.GetOutputFile(),
3139 m_debugger.GetErrorFile(),
Greg Clayton340b0302014-02-05 17:57:57 +00003140 eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult,
Greg Clayton44d93782014-01-27 23:43:24 +00003141 "lldb",
3142 m_debugger.GetPrompt(),
3143 multiple_lines,
Greg Claytonf6913cd2014-03-07 00:53:24 +00003144 0, // Don't show line numbers
Greg Clayton44d93782014-01-27 23:43:24 +00003145 *this));
3146 m_debugger.PushIOHandler(m_command_io_handler_sp);
3147
3148 if (auto_handle_events)
3149 m_debugger.StartEventHandlerThread();
3150
3151 if (spawn_thread)
3152 {
3153 m_debugger.StartIOHandlerThread();
3154 }
3155 else
3156 {
3157 m_debugger.ExecuteIOHanders();
3158
3159 if (auto_handle_events)
3160 m_debugger.StopEventHandlerThread();
3161 }
3162
3163}
3164