blob: 0fca4f2e7837533ae8dfc1e5d6a689f5dd164087 [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
Jim Ingham1624a2d2014-05-05 02:26:40 +00001459 ExpressionResults 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
Jim Ingham8646d3c2014-05-05 02:47:44 +00001464 if (expr_result == eExpressionCompleted)
Greg Clayton5a314712011-10-14 07:41:33 +00001465 {
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 {
Jim Ingham8646d3c2014-05-05 02:47:44 +00001499 case eExpressionSetupError:
Greg Clayton5a314712011-10-14 07:41:33 +00001500 error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
1501 break;
Jim Ingham8646d3c2014-05-05 02:47:44 +00001502 case eExpressionParseError:
Jim Ingham1624a2d2014-05-05 02:26:40 +00001503 error.SetErrorStringWithFormat ("expression parse error for the expression '%s'", expr_str.c_str());
1504 break;
Jim Ingham8646d3c2014-05-05 02:47:44 +00001505 case eExpressionResultUnavailable:
Jim Ingham1624a2d2014-05-05 02:26:40 +00001506 error.SetErrorStringWithFormat ("expression error fetching result for the expression '%s'", expr_str.c_str());
Jim Ingham8646d3c2014-05-05 02:47:44 +00001507 case eExpressionCompleted:
Greg Clayton5a314712011-10-14 07:41:33 +00001508 break;
Jim Ingham8646d3c2014-05-05 02:47:44 +00001509 case eExpressionDiscarded:
Greg Clayton5a314712011-10-14 07:41:33 +00001510 error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
1511 break;
Jim Ingham8646d3c2014-05-05 02:47:44 +00001512 case eExpressionInterrupted:
Greg Clayton5a314712011-10-14 07:41:33 +00001513 error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
1514 break;
Jim Ingham8646d3c2014-05-05 02:47:44 +00001515 case eExpressionHitBreakpoint:
Jim Ingham184e9812013-01-15 02:47:48 +00001516 error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
1517 break;
Jim Ingham8646d3c2014-05-05 02:47:44 +00001518 case eExpressionTimedOut:
Greg Clayton5a314712011-10-14 07:41:33 +00001519 error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
1520 break;
Jim Ingham8646d3c2014-05-05 02:47:44 +00001521 case eExpressionStoppedForDebug:
Greg Claytonc28ce782013-11-08 23:38:26 +00001522 error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str());
1523 break;
Greg Clayton5a314712011-10-14 07:41:33 +00001524 }
1525 }
1526 }
1527 }
1528 }
1529 if (error.Fail())
1530 break;
1531 }
1532 }
1533 return error;
1534}
1535
1536
Caroline Tice844d2302010-12-09 22:52:49 +00001537bool
1538CommandInterpreter::HandleCommand (const char *command_line,
Enrico Granata5f5ab602012-05-31 01:09:06 +00001539 LazyBool lazy_add_to_history,
Caroline Tice844d2302010-12-09 22:52:49 +00001540 CommandReturnObject &result,
Jim Inghame16c50a2011-02-18 00:54:25 +00001541 ExecutionContext *override_context,
Johnny Chen80fdd7c2011-10-05 00:42:59 +00001542 bool repeat_on_empty_command,
1543 bool no_context_switching)
Jim Inghame16c50a2011-02-18 00:54:25 +00001544
Caroline Tice844d2302010-12-09 22:52:49 +00001545{
Jim Inghame16c50a2011-02-18 00:54:25 +00001546
Caroline Tice844d2302010-12-09 22:52:49 +00001547 bool done = false;
Ed Masted78c9572014-04-20 00:31:37 +00001548 CommandObject *cmd_obj = nullptr;
Caroline Tice844d2302010-12-09 22:52:49 +00001549 bool wants_raw_input = false;
1550 std::string command_string (command_line);
Jim Inghama5a97eb2011-07-12 03:12:18 +00001551 std::string original_command_string (command_line);
Caroline Tice844d2302010-12-09 22:52:49 +00001552
Greg Clayton5160ce52013-03-27 23:08:40 +00001553 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
Greg Clayton2d95dc9b2010-11-10 04:57:04 +00001554 Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
1555
1556 // Make a scoped cleanup object that will clear the crash description string
1557 // on exit of this function.
Ed Masted78c9572014-04-20 00:31:37 +00001558 lldb_utility::CleanUp <const char *> crash_description_cleanup(nullptr, Host::SetCrashDescription);
Greg Clayton2d95dc9b2010-11-10 04:57:04 +00001559
Caroline Tice844d2302010-12-09 22:52:49 +00001560 if (log)
1561 log->Printf ("Processing command: %s", command_line);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001562
Jim Ingham30244832010-11-04 23:08:45 +00001563 Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
1564
Johnny Chen80fdd7c2011-10-05 00:42:59 +00001565 if (!no_context_switching)
1566 UpdateExecutionContext (override_context);
Enrico Granata5f5ab602012-05-31 01:09:06 +00001567
Enrico Granata5f5ab602012-05-31 01:09:06 +00001568 bool add_to_history;
1569 if (lazy_add_to_history == eLazyBoolCalculate)
1570 add_to_history = (m_command_source_depth == 0);
1571 else
1572 add_to_history = (lazy_add_to_history == eLazyBoolYes);
1573
Jim Inghame16c50a2011-02-18 00:54:25 +00001574 bool empty_command = false;
1575 bool comment_command = false;
1576 if (command_string.empty())
1577 empty_command = true;
1578 else
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001579 {
Jim Inghame16c50a2011-02-18 00:54:25 +00001580 const char *k_space_characters = "\t\n\v\f\r ";
1581
1582 size_t non_space = command_string.find_first_not_of (k_space_characters);
1583 // Check for empty line or comment line (lines whose first
1584 // non-space character is the comment character for this interpreter)
1585 if (non_space == std::string::npos)
1586 empty_command = true;
1587 else if (command_string[non_space] == m_comment_char)
1588 comment_command = true;
Enrico Granata7594f142013-06-17 22:51:50 +00001589 else if (command_string[non_space] == CommandHistory::g_repeat_char)
Jim Inghama5a97eb2011-07-12 03:12:18 +00001590 {
Enrico Granata7594f142013-06-17 22:51:50 +00001591 const char *history_string = m_command_history.FindString(command_string.c_str() + non_space);
Ed Masted78c9572014-04-20 00:31:37 +00001592 if (history_string == nullptr)
Jim Inghama5a97eb2011-07-12 03:12:18 +00001593 {
1594 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
1595 result.SetStatus(eReturnStatusFailed);
1596 return false;
1597 }
1598 add_to_history = false;
1599 command_string = history_string;
1600 original_command_string = history_string;
1601 }
Jim Inghame16c50a2011-02-18 00:54:25 +00001602 }
1603
1604 if (empty_command)
1605 {
1606 if (repeat_on_empty_command)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001607 {
Enrico Granata7594f142013-06-17 22:51:50 +00001608 if (m_command_history.IsEmpty())
Jim Inghame16c50a2011-02-18 00:54:25 +00001609 {
1610 result.AppendError ("empty command");
1611 result.SetStatus(eReturnStatusFailed);
1612 return false;
1613 }
1614 else
1615 {
1616 command_line = m_repeat_command.c_str();
1617 command_string = command_line;
Jim Inghama5a97eb2011-07-12 03:12:18 +00001618 original_command_string = command_line;
Jim Inghame16c50a2011-02-18 00:54:25 +00001619 if (m_repeat_command.empty())
1620 {
1621 result.AppendErrorWithFormat("No auto repeat.\n");
1622 result.SetStatus (eReturnStatusFailed);
1623 return false;
1624 }
1625 }
1626 add_to_history = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001627 }
1628 else
1629 {
Jim Inghame16c50a2011-02-18 00:54:25 +00001630 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1631 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001632 }
Jim Inghame16c50a2011-02-18 00:54:25 +00001633 }
1634 else if (comment_command)
1635 {
1636 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1637 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001638 }
Caroline Tice2b5e8502011-05-11 16:07:06 +00001639
Greg Clayton5a314712011-10-14 07:41:33 +00001640
1641 Error error (PreprocessCommand (command_string));
1642
1643 if (error.Fail())
1644 {
1645 result.AppendError (error.AsCString());
1646 result.SetStatus(eReturnStatusFailed);
1647 return false;
1648 }
Caroline Tice844d2302010-12-09 22:52:49 +00001649 // Phase 1.
1650
1651 // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
1652 // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that
1653 // the user could have specified an alias, and in translating the alias there may also be command options and/or
1654 // even data (including raw text strings) that need to be found and inserted into the command line as part of
1655 // 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 +00001656 // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
Caroline Tice844d2302010-12-09 22:52:49 +00001657 // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
Caroline Ticed9d63362010-12-07 19:58:26 +00001658
Caroline Tice844d2302010-12-09 22:52:49 +00001659 StreamString revised_command_line;
Caroline Tice01274c02010-12-11 08:16:56 +00001660 size_t actual_cmd_name_len = 0;
Greg Clayton5521f992011-10-28 21:38:01 +00001661 std::string next_word;
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001662 StringList matches;
Caroline Tice844d2302010-12-09 22:52:49 +00001663 while (!done)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001664 {
Caroline Tice2b5e8502011-05-11 16:07:06 +00001665 char quote_char = '\0';
Greg Clayton5521f992011-10-28 21:38:01 +00001666 std::string suffix;
1667 ExtractCommand (command_string, next_word, suffix, quote_char);
Ed Masted78c9572014-04-20 00:31:37 +00001668 if (cmd_obj == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001669 {
Jim Ingham298f3782013-04-03 00:25:49 +00001670 std::string full_name;
1671 if (GetAliasFullName(next_word.c_str(), full_name))
Caroline Tice472362e2010-12-14 18:51:39 +00001672 {
Greg Clayton5521f992011-10-28 21:38:01 +00001673 std::string alias_result;
Jim Ingham298f3782013-04-03 00:25:49 +00001674 cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result);
Greg Clayton5521f992011-10-28 21:38:01 +00001675 revised_command_line.Printf ("%s", alias_result.c_str());
1676 if (cmd_obj)
1677 {
1678 wants_raw_input = cmd_obj->WantsRawCommandString ();
1679 actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
1680 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001681 }
1682 else
1683 {
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001684 cmd_obj = GetCommandObject (next_word.c_str(), &matches);
Greg Clayton5521f992011-10-28 21:38:01 +00001685 if (cmd_obj)
1686 {
1687 actual_cmd_name_len += next_word.length();
1688 revised_command_line.Printf ("%s", next_word.c_str());
1689 wants_raw_input = cmd_obj->WantsRawCommandString ();
1690 }
Caroline Tice2b5e8502011-05-11 16:07:06 +00001691 else
Greg Clayton5521f992011-10-28 21:38:01 +00001692 {
1693 revised_command_line.Printf ("%s", next_word.c_str());
1694 }
Caroline Tice844d2302010-12-09 22:52:49 +00001695 }
1696 }
1697 else
1698 {
Greg Clayton5521f992011-10-28 21:38:01 +00001699 if (cmd_obj->IsMultiwordObject ())
1700 {
Greg Clayton998255b2012-10-13 02:07:45 +00001701 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str());
Greg Clayton5521f992011-10-28 21:38:01 +00001702 if (sub_cmd_obj)
1703 {
1704 actual_cmd_name_len += next_word.length() + 1;
1705 revised_command_line.Printf (" %s", next_word.c_str());
1706 cmd_obj = sub_cmd_obj;
1707 wants_raw_input = cmd_obj->WantsRawCommandString ();
1708 }
1709 else
1710 {
1711 if (quote_char)
1712 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1713 else
1714 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1715 done = true;
1716 }
1717 }
Caroline Tice2b5e8502011-05-11 16:07:06 +00001718 else
Greg Clayton5521f992011-10-28 21:38:01 +00001719 {
1720 if (quote_char)
1721 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1722 else
1723 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1724 done = true;
1725 }
Caroline Tice844d2302010-12-09 22:52:49 +00001726 }
1727
Ed Masted78c9572014-04-20 00:31:37 +00001728 if (cmd_obj == nullptr)
Caroline Tice844d2302010-12-09 22:52:49 +00001729 {
Greg Claytonc7bece562013-01-25 18:06:21 +00001730 const size_t num_matches = matches.GetSize();
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001731 if (matches.GetSize() > 1) {
Greg Claytonc7bece562013-01-25 18:06:21 +00001732 StreamString error_msg;
1733 error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001734
1735 for (uint32_t i = 0; i < num_matches; ++i) {
Greg Claytonc7bece562013-01-25 18:06:21 +00001736 error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i));
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001737 }
Greg Claytonc7bece562013-01-25 18:06:21 +00001738 result.AppendRawError (error_msg.GetString().c_str());
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001739 } else {
1740 // We didn't have only one match, otherwise we wouldn't get here.
1741 assert(num_matches == 0);
1742 result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
1743 }
Caroline Tice844d2302010-12-09 22:52:49 +00001744 result.SetStatus (eReturnStatusFailed);
1745 return false;
1746 }
1747
Greg Clayton5521f992011-10-28 21:38:01 +00001748 if (cmd_obj->IsMultiwordObject ())
1749 {
1750 if (!suffix.empty())
1751 {
1752
Enrico Granataaded51d2013-06-12 00:44:43 +00001753 result.AppendErrorWithFormat ("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n",
1754 cmd_obj->GetCommandName(),
1755 next_word.empty() ? "" : next_word.c_str(),
1756 next_word.empty() ? " -- " : " ",
Greg Clayton5521f992011-10-28 21:38:01 +00001757 suffix.c_str());
1758 result.SetStatus (eReturnStatusFailed);
1759 return false;
1760 }
1761 }
1762 else
1763 {
1764 // If we found a normal command, we are done
1765 done = true;
1766 if (!suffix.empty())
1767 {
1768 switch (suffix[0])
1769 {
1770 case '/':
1771 // GDB format suffixes
Greg Clayton52ec56c2011-10-29 00:57:28 +00001772 {
1773 Options *command_options = cmd_obj->GetOptions();
1774 if (command_options && command_options->SupportsLongOption("gdb-format"))
1775 {
Greg Clayton93c62e62011-11-09 23:25:03 +00001776 std::string gdb_format_option ("--gdb-format=");
1777 gdb_format_option += (suffix.c_str() + 1);
1778
1779 bool inserted = false;
1780 std::string &cmd = revised_command_line.GetString();
1781 size_t arg_terminator_idx = FindArgumentTerminator (cmd);
1782 if (arg_terminator_idx != std::string::npos)
1783 {
1784 // Insert the gdb format option before the "--" that terminates options
1785 gdb_format_option.append(1,' ');
1786 cmd.insert(arg_terminator_idx, gdb_format_option);
1787 inserted = true;
1788 }
1789
1790 if (!inserted)
1791 revised_command_line.Printf (" %s", gdb_format_option.c_str());
1792
1793 if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
1794 revised_command_line.PutCString (" --");
Greg Clayton52ec56c2011-10-29 00:57:28 +00001795 }
1796 else
1797 {
1798 result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n",
1799 cmd_obj->GetCommandName());
1800 result.SetStatus (eReturnStatusFailed);
1801 return false;
1802 }
1803 }
Greg Clayton5521f992011-10-28 21:38:01 +00001804 break;
Johnny Chen8e9383d2011-10-31 22:22:06 +00001805
1806 default:
1807 result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n",
1808 suffix.c_str());
1809 result.SetStatus (eReturnStatusFailed);
1810 return false;
1811
Greg Clayton5521f992011-10-28 21:38:01 +00001812 }
1813 }
1814 }
Caroline Tice844d2302010-12-09 22:52:49 +00001815 if (command_string.length() == 0)
1816 done = true;
1817
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001818 }
Caroline Tice844d2302010-12-09 22:52:49 +00001819
Greg Clayton5521f992011-10-28 21:38:01 +00001820 if (!command_string.empty())
Caroline Tice844d2302010-12-09 22:52:49 +00001821 revised_command_line.Printf (" %s", command_string.c_str());
1822
1823 // End of Phase 1.
1824 // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
1825 // specified was valid; revised_command_line contains the complete command line (including command name(s)),
1826 // fully translated with all substitutions & translations taken care of (still in raw text format); and
1827 // wants_raw_input specifies whether the Execute method expects raw input or not.
1828
1829
1830 if (log)
1831 {
1832 log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
1833 log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
1834 log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
1835 }
1836
1837 // Phase 2.
1838 // Take care of things like setting up the history command & calling the appropriate Execute method on the
1839 // CommandObject, with the appropriate arguments.
1840
Ed Masted78c9572014-04-20 00:31:37 +00001841 if (cmd_obj != nullptr)
Caroline Tice844d2302010-12-09 22:52:49 +00001842 {
1843 if (add_to_history)
1844 {
1845 Args command_args (revised_command_line.GetData());
1846 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
Ed Masted78c9572014-04-20 00:31:37 +00001847 if (repeat_command != nullptr)
Caroline Tice844d2302010-12-09 22:52:49 +00001848 m_repeat_command.assign(repeat_command);
1849 else
Jim Inghama5a97eb2011-07-12 03:12:18 +00001850 m_repeat_command.assign(original_command_string.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001851
Enrico Granata7594f142013-06-17 22:51:50 +00001852 m_command_history.AppendString (original_command_string);
Caroline Tice844d2302010-12-09 22:52:49 +00001853 }
1854
1855 command_string = revised_command_line.GetData();
1856 std::string command_name (cmd_obj->GetCommandName());
Caroline Tice01274c02010-12-11 08:16:56 +00001857 std::string remainder;
1858 if (actual_cmd_name_len < command_string.length())
1859 remainder = command_string.substr (actual_cmd_name_len); // Note: 'actual_cmd_name_len' may be considerably shorter
1860 // than cmd_obj->GetCommandName(), because name completion
1861 // allows users to enter short versions of the names,
1862 // e.g. 'br s' for 'breakpoint set'.
Caroline Tice844d2302010-12-09 22:52:49 +00001863
1864 // Remove any initial spaces
1865 std::string white_space (" \t\v");
1866 size_t pos = remainder.find_first_not_of (white_space);
1867 if (pos != 0 && pos != std::string::npos)
Greg Claytona3482592011-04-22 20:58:45 +00001868 remainder.erase(0, pos);
Caroline Tice844d2302010-12-09 22:52:49 +00001869
1870 if (log)
Jason Molendabfb36ff2011-08-25 00:20:04 +00001871 log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001872
Jim Ingham5a988412012-06-08 21:56:10 +00001873 cmd_obj->Execute (remainder.c_str(), result);
Caroline Tice844d2302010-12-09 22:52:49 +00001874 }
1875 else
1876 {
1877 // We didn't find the first command object, so complete the first argument.
1878 Args command_args (revised_command_line.GetData());
1879 StringList matches;
1880 int num_matches;
1881 int cursor_index = 0;
1882 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
1883 bool word_complete;
1884 num_matches = HandleCompletionMatches (command_args,
1885 cursor_index,
1886 cursor_char_position,
1887 0,
1888 -1,
1889 word_complete,
1890 matches);
1891
1892 if (num_matches > 0)
1893 {
1894 std::string error_msg;
1895 error_msg.assign ("ambiguous command '");
1896 error_msg.append(command_args.GetArgumentAtIndex(0));
1897 error_msg.append ("'.");
1898
1899 error_msg.append (" Possible completions:");
1900 for (int i = 0; i < num_matches; i++)
1901 {
1902 error_msg.append ("\n\t");
1903 error_msg.append (matches.GetStringAtIndex (i));
1904 }
1905 error_msg.append ("\n");
Greg Claytonc7bece562013-01-25 18:06:21 +00001906 result.AppendRawError (error_msg.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001907 }
1908 else
1909 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
1910
1911 result.SetStatus (eReturnStatusFailed);
1912 }
1913
Jason Molendabfb36ff2011-08-25 00:20:04 +00001914 if (log)
1915 log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
1916
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001917 return result.Succeeded();
1918}
1919
1920int
1921CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
1922 int &cursor_index,
1923 int &cursor_char_position,
1924 int match_start_point,
1925 int max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +00001926 bool &word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001927 StringList &matches)
1928{
1929 int num_command_matches = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001930 bool look_for_subcommand = false;
Jim Ingham558ce122010-06-30 05:02:46 +00001931
1932 // For any of the command completions a unique match will be a complete word.
1933 word_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001934
1935 if (cursor_index == -1)
1936 {
1937 // We got nothing on the command line, so return the list of commands
Jim Ingham279a6c22010-07-06 22:46:59 +00001938 bool include_aliases = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001939 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
1940 }
1941 else if (cursor_index == 0)
1942 {
1943 // The cursor is in the first argument, so just do a lookup in the dictionary.
Jim Ingham279a6c22010-07-06 22:46:59 +00001944 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001945 num_command_matches = matches.GetSize();
1946
1947 if (num_command_matches == 1
1948 && cmd_obj && cmd_obj->IsMultiwordObject()
Ed Masted78c9572014-04-20 00:31:37 +00001949 && matches.GetStringAtIndex(0) != nullptr
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001950 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
1951 {
Greg Clayton765d2e22013-12-10 19:14:04 +00001952 if (parsed_line.GetArgumentCount() == 1)
1953 {
1954 word_complete = true;
1955 }
1956 else
1957 {
1958 look_for_subcommand = true;
1959 num_command_matches = 0;
1960 matches.DeleteStringAtIndex(0);
1961 parsed_line.AppendArgument ("");
1962 cursor_index++;
1963 cursor_char_position = 0;
1964 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001965 }
1966 }
1967
1968 if (cursor_index > 0 || look_for_subcommand)
1969 {
1970 // We are completing further on into a commands arguments, so find the command and tell it
1971 // to complete the command.
1972 // First see if there is a matching initial command:
Jim Ingham279a6c22010-07-06 22:46:59 +00001973 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
Ed Masted78c9572014-04-20 00:31:37 +00001974 if (command_object == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001975 {
1976 return 0;
1977 }
1978 else
1979 {
1980 parsed_line.Shift();
1981 cursor_index--;
Greg Claytona7015092010-09-18 01:14:36 +00001982 num_command_matches = command_object->HandleCompletion (parsed_line,
Greg Clayton66111032010-06-23 01:19:29 +00001983 cursor_index,
1984 cursor_char_position,
1985 match_start_point,
Jim Ingham558ce122010-06-30 05:02:46 +00001986 max_return_elements,
1987 word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001988 matches);
1989 }
1990 }
1991
1992 return num_command_matches;
1993
1994}
1995
1996int
1997CommandInterpreter::HandleCompletion (const char *current_line,
1998 const char *cursor,
1999 const char *last_char,
2000 int match_start_point,
2001 int max_return_elements,
2002 StringList &matches)
2003{
2004 // We parse the argument up to the cursor, so the last argument in parsed_line is
2005 // the one containing the cursor, and the cursor is after the last character.
2006
2007 Args parsed_line(current_line, last_char - current_line);
2008 Args partial_parsed_line(current_line, cursor - current_line);
2009
Jim Inghama5a97eb2011-07-12 03:12:18 +00002010 // Don't complete comments, and if the line we are completing is just the history repeat character,
2011 // substitute the appropriate history line.
2012 const char *first_arg = parsed_line.GetArgumentAtIndex(0);
2013 if (first_arg)
2014 {
2015 if (first_arg[0] == m_comment_char)
2016 return 0;
Enrico Granata7594f142013-06-17 22:51:50 +00002017 else if (first_arg[0] == CommandHistory::g_repeat_char)
Jim Inghama5a97eb2011-07-12 03:12:18 +00002018 {
Enrico Granata7594f142013-06-17 22:51:50 +00002019 const char *history_string = m_command_history.FindString (first_arg);
Ed Masted78c9572014-04-20 00:31:37 +00002020 if (history_string != nullptr)
Jim Inghama5a97eb2011-07-12 03:12:18 +00002021 {
2022 matches.Clear();
2023 matches.InsertStringAtIndex(0, history_string);
2024 return -2;
2025 }
2026 else
2027 return 0;
2028
2029 }
2030 }
2031
2032
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002033 int num_args = partial_parsed_line.GetArgumentCount();
2034 int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
2035 int cursor_char_position;
2036
2037 if (cursor_index == -1)
2038 cursor_char_position = 0;
2039 else
2040 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
Jim Inghamfe0c4252010-12-14 19:56:01 +00002041
2042 if (cursor > current_line && cursor[-1] == ' ')
2043 {
2044 // We are just after a space. If we are in an argument, then we will continue
2045 // parsing, but if we are between arguments, then we have to complete whatever the next
2046 // element would be.
2047 // We can distinguish the two cases because if we are in an argument (e.g. because the space is
2048 // protected by a quote) then the space will also be in the parsed argument...
2049
2050 const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
2051 if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
2052 {
Greg Clayton765d2e22013-12-10 19:14:04 +00002053 parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0');
Jim Inghamfe0c4252010-12-14 19:56:01 +00002054 cursor_index++;
2055 cursor_char_position = 0;
2056 }
2057 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002058
2059 int num_command_matches;
2060
2061 matches.Clear();
2062
2063 // Only max_return_elements == -1 is supported at present:
2064 assert (max_return_elements == -1);
Jim Ingham558ce122010-06-30 05:02:46 +00002065 bool word_complete;
Greg Clayton66111032010-06-23 01:19:29 +00002066 num_command_matches = HandleCompletionMatches (parsed_line,
2067 cursor_index,
2068 cursor_char_position,
2069 match_start_point,
Jim Ingham558ce122010-06-30 05:02:46 +00002070 max_return_elements,
2071 word_complete,
Greg Clayton66111032010-06-23 01:19:29 +00002072 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002073
2074 if (num_command_matches <= 0)
2075 return num_command_matches;
2076
2077 if (num_args == 0)
2078 {
2079 // If we got an empty string, insert nothing.
2080 matches.InsertStringAtIndex(0, "");
2081 }
2082 else
2083 {
2084 // Now figure out if there is a common substring, and if so put that in element 0, otherwise
2085 // put an empty string in element 0.
2086 std::string command_partial_str;
2087 if (cursor_index >= 0)
Jim Ingham49e80a12010-10-22 18:47:16 +00002088 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
2089 parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002090
2091 std::string common_prefix;
2092 matches.LongestCommonPrefix (common_prefix);
Greg Claytonc7bece562013-01-25 18:06:21 +00002093 const size_t partial_name_len = command_partial_str.size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002094
2095 // If we matched a unique single command, add a space...
Jim Ingham558ce122010-06-30 05:02:46 +00002096 // Only do this if the completer told us this was a complete word, however...
2097 if (num_command_matches == 1 && word_complete)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002098 {
2099 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
2100 if (quote_char != '\0')
2101 common_prefix.push_back(quote_char);
2102
2103 common_prefix.push_back(' ');
2104 }
2105 common_prefix.erase (0, partial_name_len);
2106 matches.InsertStringAtIndex(0, common_prefix.c_str());
2107 }
2108 return num_command_matches;
2109}
2110
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002111
2112CommandInterpreter::~CommandInterpreter ()
2113{
2114}
2115
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002116void
Greg Clayton44d93782014-01-27 23:43:24 +00002117CommandInterpreter::UpdatePrompt (const char *new_prompt)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002118{
Greg Clayton44d93782014-01-27 23:43:24 +00002119 EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));;
2120 BroadcastEvent (prompt_change_event_sp);
2121 if (m_command_io_handler_sp)
2122 m_command_io_handler_sp->SetPrompt(new_prompt);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002123}
2124
Jim Ingham97a6dc72010-10-04 19:49:29 +00002125
2126bool
2127CommandInterpreter::Confirm (const char *message, bool default_answer)
2128{
Jim Ingham3bcdb292010-10-04 22:44:14 +00002129 // Check AutoConfirm first:
2130 if (m_debugger.GetAutoConfirm())
2131 return default_answer;
Greg Clayton44d93782014-01-27 23:43:24 +00002132
2133 IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger,
2134 message,
2135 default_answer);
2136 IOHandlerSP io_handler_sp (confirm);
2137 m_debugger.RunIOHandler (io_handler_sp);
2138 return confirm->GetResponse();
Jim Ingham97a6dc72010-10-04 19:49:29 +00002139}
2140
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002141OptionArgVectorSP
2142CommandInterpreter::GetAliasOptions (const char *alias_name)
2143{
2144 OptionArgMap::iterator pos;
2145 OptionArgVectorSP ret_val;
2146
2147 std::string alias (alias_name);
2148
2149 if (HasAliasOptions())
2150 {
2151 pos = m_alias_options.find (alias);
2152 if (pos != m_alias_options.end())
2153 ret_val = pos->second;
2154 }
2155
2156 return ret_val;
2157}
2158
2159void
2160CommandInterpreter::RemoveAliasOptions (const char *alias_name)
2161{
2162 OptionArgMap::iterator pos = m_alias_options.find(alias_name);
2163 if (pos != m_alias_options.end())
2164 {
2165 m_alias_options.erase (pos);
2166 }
2167}
2168
2169void
2170CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
2171{
2172 m_alias_options[alias_name] = option_arg_vector_sp;
2173}
2174
2175bool
2176CommandInterpreter::HasCommands ()
2177{
2178 return (!m_command_dict.empty());
2179}
2180
2181bool
2182CommandInterpreter::HasAliases ()
2183{
2184 return (!m_alias_dict.empty());
2185}
2186
2187bool
2188CommandInterpreter::HasUserCommands ()
2189{
2190 return (!m_user_dict.empty());
2191}
2192
2193bool
2194CommandInterpreter::HasAliasOptions ()
2195{
2196 return (!m_alias_options.empty());
2197}
2198
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002199void
Caroline Tice4ab31c92010-10-12 21:57:09 +00002200CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
2201 const char *alias_name,
2202 Args &cmd_args,
Caroline Ticed9d63362010-12-07 19:58:26 +00002203 std::string &raw_input_string,
Caroline Tice4ab31c92010-10-12 21:57:09 +00002204 CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002205{
2206 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
Caroline Ticed9d63362010-12-07 19:58:26 +00002207
2208 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002209
Caroline Ticed9d63362010-12-07 19:58:26 +00002210 // Make sure that the alias name is the 0th element in cmd_args
2211 std::string alias_name_str = alias_name;
2212 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
2213 cmd_args.Unshift (alias_name);
2214
2215 Args new_args (alias_cmd_obj->GetCommandName());
2216 if (new_args.GetArgumentCount() == 2)
2217 new_args.Shift();
2218
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002219 if (option_arg_vector_sp.get())
2220 {
Caroline Ticed9d63362010-12-07 19:58:26 +00002221 if (wants_raw_input)
2222 {
2223 // We have a command that both has command options and takes raw input. Make *sure* it has a
2224 // " -- " in the right place in the raw_input_string.
2225 size_t pos = raw_input_string.find(" -- ");
2226 if (pos == std::string::npos)
2227 {
2228 // None found; assume it goes at the beginning of the raw input string
2229 raw_input_string.insert (0, " -- ");
2230 }
2231 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002232
2233 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
Greg Claytonc7bece562013-01-25 18:06:21 +00002234 const size_t old_size = cmd_args.GetArgumentCount();
Caroline Tice4ab31c92010-10-12 21:57:09 +00002235 std::vector<bool> used (old_size + 1, false);
2236
2237 used[0] = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002238
Andy Gibbsa297a972013-06-19 19:04:53 +00002239 for (size_t i = 0; i < option_arg_vector->size(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002240 {
2241 OptionArgPair option_pair = (*option_arg_vector)[i];
Caroline Ticed9d63362010-12-07 19:58:26 +00002242 OptionArgValue value_pair = option_pair.second;
2243 int value_type = value_pair.first;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002244 std::string option = option_pair.first;
Caroline Ticed9d63362010-12-07 19:58:26 +00002245 std::string value = value_pair.second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002246 if (option.compare ("<argument>") == 0)
Caroline Ticed9d63362010-12-07 19:58:26 +00002247 {
2248 if (!wants_raw_input
2249 || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
2250 new_args.AppendArgument (value.c_str());
2251 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002252 else
2253 {
Virgile Belloe2607b52013-09-05 16:42:23 +00002254 if (value_type != OptionParser::eOptionalArgument)
Caroline Ticed9d63362010-12-07 19:58:26 +00002255 new_args.AppendArgument (option.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002256 if (value.compare ("<no-argument>") != 0)
2257 {
2258 int index = GetOptionArgumentPosition (value.c_str());
2259 if (index == 0)
Caroline Ticed9d63362010-12-07 19:58:26 +00002260 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002261 // value was NOT a positional argument; must be a real value
Virgile Belloe2607b52013-09-05 16:42:23 +00002262 if (value_type != OptionParser::eOptionalArgument)
Caroline Ticed9d63362010-12-07 19:58:26 +00002263 new_args.AppendArgument (value.c_str());
2264 else
2265 {
2266 char buffer[255];
2267 ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
2268 new_args.AppendArgument (buffer);
2269 }
2270
2271 }
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +00002272 else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002273 {
2274 result.AppendErrorWithFormat
2275 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
2276 index);
2277 result.SetStatus (eReturnStatusFailed);
2278 return;
2279 }
2280 else
2281 {
Caroline Ticed9d63362010-12-07 19:58:26 +00002282 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2283 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
2284 if (strpos != std::string::npos)
2285 {
2286 raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
2287 }
2288
Virgile Belloe2607b52013-09-05 16:42:23 +00002289 if (value_type != OptionParser::eOptionalArgument)
Caroline Ticed9d63362010-12-07 19:58:26 +00002290 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
2291 else
2292 {
2293 char buffer[255];
2294 ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
2295 cmd_args.GetArgumentAtIndex (index));
2296 new_args.AppendArgument (buffer);
2297 }
Caroline Tice4ab31c92010-10-12 21:57:09 +00002298 used[index] = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002299 }
2300 }
2301 }
2302 }
2303
Andy Gibbsa297a972013-06-19 19:04:53 +00002304 for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002305 {
Caroline Ticed9d63362010-12-07 19:58:26 +00002306 if (!used[j] && !wants_raw_input)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002307 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
2308 }
2309
2310 cmd_args.Clear();
2311 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2312 }
2313 else
2314 {
2315 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Caroline Ticed9d63362010-12-07 19:58:26 +00002316 // This alias was not created with any options; nothing further needs to be done, unless it is a command that
2317 // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
2318 // input string.
2319 if (wants_raw_input)
2320 {
2321 cmd_args.Clear();
2322 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2323 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002324 return;
2325 }
2326
2327 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2328 return;
2329}
2330
2331
2332int
2333CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
2334{
2335 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
2336 // of zero.
2337
2338 char *cptr = (char *) in_string;
2339
2340 // Does it start with '%'
2341 if (cptr[0] == '%')
2342 {
2343 ++cptr;
2344
2345 // Is the rest of it entirely digits?
2346 if (isdigit (cptr[0]))
2347 {
2348 const char *start = cptr;
2349 while (isdigit (cptr[0]))
2350 ++cptr;
2351
2352 // We've gotten to the end of the digits; are we at the end of the string?
2353 if (cptr[0] == '\0')
2354 position = atoi (start);
2355 }
2356 }
2357
2358 return position;
2359}
2360
2361void
2362CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
2363{
Jim Ingham16e0c682011-08-12 23:34:31 +00002364 FileSpec init_file;
Greg Clayton14a35512011-09-11 00:01:44 +00002365 if (in_cwd)
Jim Ingham16e0c682011-08-12 23:34:31 +00002366 {
Greg Clayton14a35512011-09-11 00:01:44 +00002367 // In the current working directory we don't load any program specific
2368 // .lldbinit files, we only look for a "./.lldbinit" file.
2369 if (m_skip_lldbinit_files)
2370 return;
2371
2372 init_file.SetFile ("./.lldbinit", true);
Jim Ingham16e0c682011-08-12 23:34:31 +00002373 }
Greg Clayton14a35512011-09-11 00:01:44 +00002374 else
Jim Ingham16e0c682011-08-12 23:34:31 +00002375 {
Greg Clayton14a35512011-09-11 00:01:44 +00002376 // If we aren't looking in the current working directory we are looking
2377 // in the home directory. We will first see if there is an application
2378 // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
2379 // "-" and the name of the program. If this file doesn't exist, we fall
2380 // back to just the "~/.lldbinit" file. We also obey any requests to not
2381 // load the init files.
2382 const char *init_file_path = "~/.lldbinit";
2383
2384 if (m_skip_app_init_files == false)
2385 {
2386 FileSpec program_file_spec (Host::GetProgramFileSpec());
2387 const char *program_name = program_file_spec.GetFilename().AsCString();
Jim Ingham16e0c682011-08-12 23:34:31 +00002388
Greg Clayton14a35512011-09-11 00:01:44 +00002389 if (program_name)
2390 {
2391 char program_init_file_name[PATH_MAX];
2392 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name);
2393 init_file.SetFile (program_init_file_name, true);
2394 if (!init_file.Exists())
2395 init_file.Clear();
2396 }
2397 }
2398
2399 if (!init_file && !m_skip_lldbinit_files)
2400 init_file.SetFile (init_file_path, true);
2401 }
2402
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002403 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
2404 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
2405
2406 if (init_file.Exists())
2407 {
Greg Clayton44d93782014-01-27 23:43:24 +00002408 const bool saved_batch = SetBatchCommandMode (true);
Greg Clayton340b0302014-02-05 17:57:57 +00002409 HandleCommandsFromFile (init_file,
Ed Masted78c9572014-04-20 00:31:37 +00002410 nullptr, // Execution context
Greg Clayton340b0302014-02-05 17:57:57 +00002411 eLazyBoolYes, // Stop on continue
2412 eLazyBoolNo, // Stop on error
2413 eLazyBoolNo, // Don't echo commands
2414 eLazyBoolNo, // Don't print command output
2415 eLazyBoolNo, // Don't add the commands that are sourced into the history buffer
2416 result);
Greg Clayton44d93782014-01-27 23:43:24 +00002417 SetBatchCommandMode (saved_batch);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002418 }
2419 else
2420 {
2421 // nothing to be done if the file doesn't exist
2422 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2423 }
2424}
2425
Greg Clayton8b82f082011-04-12 05:54:46 +00002426PlatformSP
2427CommandInterpreter::GetPlatform (bool prefer_target_platform)
2428{
2429 PlatformSP platform_sp;
Greg Claytonc14ee322011-09-22 04:58:26 +00002430 if (prefer_target_platform)
2431 {
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00002432 ExecutionContext exe_ctx(GetExecutionContext());
2433 Target *target = exe_ctx.GetTargetPtr();
Greg Claytonc14ee322011-09-22 04:58:26 +00002434 if (target)
2435 platform_sp = target->GetPlatform();
2436 }
Greg Clayton8b82f082011-04-12 05:54:46 +00002437
2438 if (!platform_sp)
2439 platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
2440 return platform_sp;
2441}
2442
Jim Inghame16c50a2011-02-18 00:54:25 +00002443void
Jim Inghambad87fe2011-03-11 01:51:49 +00002444CommandInterpreter::HandleCommands (const StringList &commands,
Jim Inghame16c50a2011-02-18 00:54:25 +00002445 ExecutionContext *override_context,
2446 bool stop_on_continue,
2447 bool stop_on_error,
2448 bool echo_commands,
2449 bool print_results,
Enrico Granata5f5ab602012-05-31 01:09:06 +00002450 LazyBool add_to_history,
Jim Inghame16c50a2011-02-18 00:54:25 +00002451 CommandReturnObject &result)
2452{
2453 size_t num_lines = commands.GetSize();
Jim Inghame16c50a2011-02-18 00:54:25 +00002454
2455 // If we are going to continue past a "continue" then we need to run the commands synchronously.
2456 // Make sure you reset this value anywhere you return from the function.
2457
2458 bool old_async_execution = m_debugger.GetAsyncExecution();
2459
2460 // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
2461 // cause series of commands that change the context, then do an operation that relies on that context to fail.
2462
Ed Masted78c9572014-04-20 00:31:37 +00002463 if (override_context != nullptr)
Greg Clayton8b82f082011-04-12 05:54:46 +00002464 UpdateExecutionContext (override_context);
Jim Inghame16c50a2011-02-18 00:54:25 +00002465
2466 if (!stop_on_continue)
2467 {
2468 m_debugger.SetAsyncExecution (false);
2469 }
2470
Andy Gibbsa297a972013-06-19 19:04:53 +00002471 for (size_t idx = 0; idx < num_lines; idx++)
Jim Inghame16c50a2011-02-18 00:54:25 +00002472 {
2473 const char *cmd = commands.GetStringAtIndex(idx);
2474 if (cmd[0] == '\0')
2475 continue;
2476
Jim Inghame16c50a2011-02-18 00:54:25 +00002477 if (echo_commands)
2478 {
2479 result.AppendMessageWithFormat ("%s %s\n",
Greg Clayton44d93782014-01-27 23:43:24 +00002480 m_debugger.GetPrompt(),
2481 cmd);
Jim Inghame16c50a2011-02-18 00:54:25 +00002482 }
2483
Greg Clayton9d0402b2011-02-20 02:15:07 +00002484 CommandReturnObject tmp_result;
Johnny Chen80fdd7c2011-10-05 00:42:59 +00002485 // If override_context is not NULL, pass no_context_switching = true for
2486 // HandleCommand() since we updated our context already.
Jim Ingham076b7fc2013-05-02 23:15:37 +00002487
2488 // We might call into a regex or alias command, in which case the add_to_history will get lost. This
2489 // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
2490 if (!add_to_history)
2491 m_command_source_depth++;
Enrico Granata5f5ab602012-05-31 01:09:06 +00002492 bool success = HandleCommand(cmd, add_to_history, tmp_result,
Ed Masted78c9572014-04-20 00:31:37 +00002493 nullptr, /* override_context */
Johnny Chen80fdd7c2011-10-05 00:42:59 +00002494 true, /* repeat_on_empty_command */
Ed Masted78c9572014-04-20 00:31:37 +00002495 override_context != nullptr /* no_context_switching */);
Jim Ingham076b7fc2013-05-02 23:15:37 +00002496 if (!add_to_history)
2497 m_command_source_depth--;
Jim Inghame16c50a2011-02-18 00:54:25 +00002498
2499 if (print_results)
2500 {
2501 if (tmp_result.Succeeded())
Jim Ingham85e8b812011-02-19 02:53:09 +00002502 result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
Jim Inghame16c50a2011-02-18 00:54:25 +00002503 }
2504
2505 if (!success || !tmp_result.Succeeded())
2506 {
Jim Inghama5038812012-04-24 02:25:07 +00002507 const char *error_msg = tmp_result.GetErrorData();
Ed Masted78c9572014-04-20 00:31:37 +00002508 if (error_msg == nullptr || error_msg[0] == '\0')
Jim Inghama5038812012-04-24 02:25:07 +00002509 error_msg = "<unknown error>.\n";
Jim Inghame16c50a2011-02-18 00:54:25 +00002510 if (stop_on_error)
2511 {
Deepak Panickal99fbc072014-03-03 15:39:47 +00002512 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s",
2513 (uint64_t)idx, cmd, error_msg);
Jim Inghame16c50a2011-02-18 00:54:25 +00002514 result.SetStatus (eReturnStatusFailed);
2515 m_debugger.SetAsyncExecution (old_async_execution);
2516 return;
2517 }
2518 else if (print_results)
2519 {
Deepak Panickal99fbc072014-03-03 15:39:47 +00002520 result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s",
2521 (uint64_t)idx + 1,
Jim Inghame16c50a2011-02-18 00:54:25 +00002522 cmd,
Jim Inghama5038812012-04-24 02:25:07 +00002523 error_msg);
Jim Inghame16c50a2011-02-18 00:54:25 +00002524 }
2525 }
2526
Caroline Tice969ed3d2011-05-02 20:41:46 +00002527 if (result.GetImmediateOutputStream())
2528 result.GetImmediateOutputStream()->Flush();
2529
2530 if (result.GetImmediateErrorStream())
2531 result.GetImmediateErrorStream()->Flush();
2532
Jim Inghame16c50a2011-02-18 00:54:25 +00002533 // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
2534 // could be running (for instance in Breakpoint Commands.
2535 // So we check the return value to see if it is has running in it.
2536 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
2537 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
2538 {
2539 if (stop_on_continue)
2540 {
2541 // If we caused the target to proceed, and we're going to stop in that case, set the
2542 // status in our real result before returning. This is an error if the continue was not the
2543 // last command in the set of commands to be run.
2544 if (idx != num_lines - 1)
Deepak Panickal99fbc072014-03-03 15:39:47 +00002545 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' continued the target.\n",
2546 (uint64_t)idx + 1, cmd);
Jim Inghame16c50a2011-02-18 00:54:25 +00002547 else
Deepak Panickal99fbc072014-03-03 15:39:47 +00002548 result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' continued the target.\n", (uint64_t)idx + 1, cmd);
Jim Inghame16c50a2011-02-18 00:54:25 +00002549
2550 result.SetStatus(tmp_result.GetStatus());
2551 m_debugger.SetAsyncExecution (old_async_execution);
2552
2553 return;
2554 }
2555 }
2556
2557 }
2558
2559 result.SetStatus (eReturnStatusSuccessFinishResult);
2560 m_debugger.SetAsyncExecution (old_async_execution);
2561
2562 return;
2563}
2564
Greg Clayton340b0302014-02-05 17:57:57 +00002565// Make flags that we can pass into the IOHandler so our delegates can do the right thing
2566enum {
2567 eHandleCommandFlagStopOnContinue = (1u << 0),
2568 eHandleCommandFlagStopOnError = (1u << 1),
2569 eHandleCommandFlagEchoCommand = (1u << 2),
2570 eHandleCommandFlagPrintResult = (1u << 3)
2571};
2572
Jim Inghame16c50a2011-02-18 00:54:25 +00002573void
2574CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
2575 ExecutionContext *context,
Greg Clayton340b0302014-02-05 17:57:57 +00002576 LazyBool stop_on_continue,
2577 LazyBool stop_on_error,
2578 LazyBool echo_command,
2579 LazyBool print_result,
Enrico Granata5f5ab602012-05-31 01:09:06 +00002580 LazyBool add_to_history,
Jim Inghame16c50a2011-02-18 00:54:25 +00002581 CommandReturnObject &result)
2582{
2583 if (cmd_file.Exists())
2584 {
Greg Clayton44d93782014-01-27 23:43:24 +00002585 StreamFileSP input_file_sp (new StreamFile());
2586
2587 std::string cmd_file_path = cmd_file.GetPath();
2588 Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead);
2589
2590 if (error.Success())
2591 {
2592 Debugger &debugger = GetDebugger();
2593
Greg Clayton340b0302014-02-05 17:57:57 +00002594 uint32_t flags = 0;
2595
2596 if (stop_on_continue == eLazyBoolCalculate)
2597 {
2598 if (m_command_source_flags.empty())
2599 {
Greg Claytone4e462c2014-02-05 21:03:22 +00002600 // Stop on continue by default
Greg Clayton340b0302014-02-05 17:57:57 +00002601 flags |= eHandleCommandFlagStopOnContinue;
2602 }
2603 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue)
2604 {
2605 flags |= eHandleCommandFlagStopOnContinue;
2606 }
2607 }
2608 else if (stop_on_continue == eLazyBoolYes)
2609 {
2610 flags |= eHandleCommandFlagStopOnContinue;
2611 }
2612
2613 if (stop_on_error == eLazyBoolCalculate)
2614 {
2615 if (m_command_source_flags.empty())
2616 {
2617 if (GetStopCmdSourceOnError())
2618 flags |= eHandleCommandFlagStopOnError;
2619 }
2620 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError)
2621 {
2622 flags |= eHandleCommandFlagStopOnError;
2623 }
2624 }
2625 else if (stop_on_error == eLazyBoolYes)
2626 {
2627 flags |= eHandleCommandFlagStopOnError;
2628 }
2629
2630 if (echo_command == eLazyBoolCalculate)
2631 {
2632 if (m_command_source_flags.empty())
2633 {
2634 // Echo command by default
2635 flags |= eHandleCommandFlagEchoCommand;
2636 }
2637 else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand)
2638 {
2639 flags |= eHandleCommandFlagEchoCommand;
2640 }
2641 }
2642 else if (echo_command == eLazyBoolYes)
2643 {
2644 flags |= eHandleCommandFlagEchoCommand;
2645 }
2646
2647 if (print_result == eLazyBoolCalculate)
2648 {
2649 if (m_command_source_flags.empty())
2650 {
Greg Claytone4e462c2014-02-05 21:03:22 +00002651 // Print output by default
2652 flags |= eHandleCommandFlagPrintResult;
Greg Clayton340b0302014-02-05 17:57:57 +00002653 }
Greg Claytone4e462c2014-02-05 21:03:22 +00002654 else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult)
Greg Clayton340b0302014-02-05 17:57:57 +00002655 {
Greg Claytone4e462c2014-02-05 21:03:22 +00002656 flags |= eHandleCommandFlagPrintResult;
Greg Clayton340b0302014-02-05 17:57:57 +00002657 }
2658 }
2659 else if (print_result == eLazyBoolYes)
2660 {
Greg Claytone4e462c2014-02-05 21:03:22 +00002661 flags |= eHandleCommandFlagPrintResult;
2662 }
2663
2664 if (flags & eHandleCommandFlagPrintResult)
2665 {
Greg Clayton8ee67312014-02-05 21:46:20 +00002666 debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str());
Greg Clayton340b0302014-02-05 17:57:57 +00002667 }
2668
2669 // Used for inheriting the right settings when "command source" might have
2670 // nested "command source" commands
Greg Claytone4e462c2014-02-05 21:03:22 +00002671 lldb::StreamFileSP empty_stream_sp;
Greg Clayton340b0302014-02-05 17:57:57 +00002672 m_command_source_flags.push_back(flags);
Greg Clayton44d93782014-01-27 23:43:24 +00002673 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
2674 input_file_sp,
Greg Claytone4e462c2014-02-05 21:03:22 +00002675 empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream
2676 empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream
Greg Clayton340b0302014-02-05 17:57:57 +00002677 flags,
Ed Masted78c9572014-04-20 00:31:37 +00002678 nullptr, // Pass in NULL for "editline_name" so no history is saved, or written
Greg Clayton8ee67312014-02-05 21:46:20 +00002679 debugger.GetPrompt(),
Greg Clayton44d93782014-01-27 23:43:24 +00002680 false, // Not multi-line
Greg Claytonf6913cd2014-03-07 00:53:24 +00002681 0,
Greg Clayton44d93782014-01-27 23:43:24 +00002682 *this));
Greg Clayton8ee67312014-02-05 21:46:20 +00002683 const bool old_async_execution = debugger.GetAsyncExecution();
2684
2685 // Set synchronous execution if we not stopping when we continue
2686 if ((flags & eHandleCommandFlagStopOnContinue) == 0)
2687 debugger.SetAsyncExecution (false);
2688
Greg Clayton340b0302014-02-05 17:57:57 +00002689 m_command_source_depth++;
Greg Clayton8ee67312014-02-05 21:46:20 +00002690
2691 debugger.RunIOHandler(io_handler_sp);
Greg Clayton340b0302014-02-05 17:57:57 +00002692 if (!m_command_source_flags.empty())
2693 m_command_source_flags.pop_back();
2694 m_command_source_depth--;
Greg Clayton44d93782014-01-27 23:43:24 +00002695 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton8ee67312014-02-05 21:46:20 +00002696 debugger.SetAsyncExecution (old_async_execution);
Greg Clayton44d93782014-01-27 23:43:24 +00002697 }
2698 else
2699 {
2700 result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString());
2701 result.SetStatus (eReturnStatusFailed);
2702 }
Greg Clayton8ee67312014-02-05 21:46:20 +00002703
2704
Jim Inghame16c50a2011-02-18 00:54:25 +00002705 }
2706 else
2707 {
2708 result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
2709 cmd_file.GetFilename().AsCString());
2710 result.SetStatus (eReturnStatusFailed);
2711 return;
2712 }
2713}
2714
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002715ScriptInterpreter *
Enrico Granatab5887262012-10-29 21:18:03 +00002716CommandInterpreter::GetScriptInterpreter (bool can_create)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002717{
Ed Masted78c9572014-04-20 00:31:37 +00002718 if (m_script_interpreter_ap.get() != nullptr)
Enrico Granatab5887262012-10-29 21:18:03 +00002719 return m_script_interpreter_ap.get();
2720
2721 if (!can_create)
Ed Masted78c9572014-04-20 00:31:37 +00002722 return nullptr;
Enrico Granatab5887262012-10-29 21:18:03 +00002723
Enrico Granataa29bdad2012-07-10 18:23:48 +00002724 // <rdar://problem/11751427>
2725 // we need to protect the initialization of the script interpreter
2726 // otherwise we could end up with two threads both trying to create
2727 // their instance of it, and for some languages (e.g. Python)
2728 // this is a bulletproof recipe for disaster!
2729 // this needs to be a function-level static because multiple Debugger instances living in the same process
2730 // still need to be isolated and not try to initialize Python concurrently
Enrico Granata8b95df22012-07-10 19:04:14 +00002731 static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
2732 Mutex::Locker interpreter_lock(g_interpreter_mutex);
Enrico Granataa29bdad2012-07-10 18:23:48 +00002733
Greg Clayton5160ce52013-03-27 23:08:40 +00002734 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Enrico Granatab5887262012-10-29 21:18:03 +00002735 if (log)
2736 log->Printf("Initializing the ScriptInterpreter now\n");
Greg Clayton66111032010-06-23 01:19:29 +00002737
Caroline Tice2f88aad2011-01-14 00:29:16 +00002738 lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
2739 switch (script_lang)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002740 {
Greg Claytondce502e2011-11-04 03:34:56 +00002741 case eScriptLanguagePython:
2742#ifndef LLDB_DISABLE_PYTHON
2743 m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
2744 break;
2745#else
2746 // Fall through to the None case when python is disabled
2747#endif
Caroline Tice2f88aad2011-01-14 00:29:16 +00002748 case eScriptLanguageNone:
2749 m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
2750 break;
Caroline Tice2f88aad2011-01-14 00:29:16 +00002751 };
2752
2753 return m_script_interpreter_ap.get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002754}
2755
2756
2757
2758bool
2759CommandInterpreter::GetSynchronous ()
2760{
2761 return m_synchronous_execution;
2762}
2763
2764void
2765CommandInterpreter::SetSynchronous (bool value)
2766{
Johnny Chenc066ab42010-10-14 01:22:03 +00002767 m_synchronous_execution = value;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002768}
2769
2770void
2771CommandInterpreter::OutputFormattedHelpText (Stream &strm,
2772 const char *word_text,
2773 const char *separator,
2774 const char *help_text,
Greg Claytonc7bece562013-01-25 18:06:21 +00002775 size_t max_word_len)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002776{
Greg Claytona7015092010-09-18 01:14:36 +00002777 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2778
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002779 int indent_size = max_word_len + strlen (separator) + 2;
2780
2781 strm.IndentMore (indent_size);
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002782
2783 StreamString text_strm;
Greg Claytonc7bece562013-01-25 18:06:21 +00002784 text_strm.Printf ("%-*s %s %s", (int)max_word_len, word_text, separator, help_text);
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002785
2786 size_t len = text_strm.GetSize();
2787 const char *text = text_strm.GetData();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002788 if (text[len - 1] == '\n')
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002789 {
2790 text_strm.EOL();
2791 len = text_strm.GetSize();
2792 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002793
2794 if (len < max_columns)
2795 {
2796 // Output it as a single line.
2797 strm.Printf ("%s", text);
2798 }
2799 else
2800 {
2801 // We need to break it up into multiple lines.
2802 bool first_line = true;
2803 int text_width;
Greg Claytonc7bece562013-01-25 18:06:21 +00002804 size_t start = 0;
2805 size_t end = start;
2806 const size_t final_end = strlen (text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002807
2808 while (end < final_end)
2809 {
2810 if (first_line)
2811 text_width = max_columns - 1;
2812 else
2813 text_width = max_columns - indent_size - 1;
2814
2815 // Don't start the 'text' on a space, since we're already outputting the indentation.
2816 if (!first_line)
2817 {
2818 while ((start < final_end) && (text[start] == ' '))
2819 start++;
2820 }
2821
2822 end = start + text_width;
2823 if (end > final_end)
2824 end = final_end;
2825 else
2826 {
2827 // If we're not at the end of the text, make sure we break the line on white space.
2828 while (end > start
2829 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
2830 end--;
Greg Clayton67cc0632012-08-22 17:17:09 +00002831 assert (end > 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002832 }
2833
Greg Claytonc7bece562013-01-25 18:06:21 +00002834 const size_t sub_len = end - start;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002835 if (start != 0)
2836 strm.EOL();
2837 if (!first_line)
2838 strm.Indent();
2839 else
2840 first_line = false;
2841 assert (start <= final_end);
2842 assert (start + sub_len <= final_end);
2843 if (sub_len > 0)
2844 strm.Write (text + start, sub_len);
2845 start = end + 1;
2846 }
2847 }
2848 strm.EOL();
2849 strm.IndentLess(indent_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002850}
2851
2852void
Enrico Granata82a7d982011-07-07 00:38:40 +00002853CommandInterpreter::OutputHelpText (Stream &strm,
2854 const char *word_text,
2855 const char *separator,
2856 const char *help_text,
2857 uint32_t max_word_len)
2858{
2859 int indent_size = max_word_len + strlen (separator) + 2;
2860
2861 strm.IndentMore (indent_size);
2862
2863 StreamString text_strm;
2864 text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
2865
2866 const uint32_t max_columns = m_debugger.GetTerminalWidth();
Enrico Granata82a7d982011-07-07 00:38:40 +00002867
2868 size_t len = text_strm.GetSize();
2869 const char *text = text_strm.GetData();
2870
2871 uint32_t chars_left = max_columns;
2872
2873 for (uint32_t i = 0; i < len; i++)
2874 {
2875 if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
2876 {
Enrico Granata82a7d982011-07-07 00:38:40 +00002877 chars_left = max_columns - indent_size;
2878 strm.EOL();
2879 strm.Indent();
2880 }
2881 else
2882 {
2883 strm.PutChar(text[i]);
2884 chars_left--;
2885 }
2886
2887 }
2888
2889 strm.EOL();
2890 strm.IndentLess(indent_size);
2891}
2892
2893void
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002894CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
Jim Inghamaf3753e2013-05-17 01:30:37 +00002895 StringList &commands_help, bool search_builtin_commands, bool search_user_commands)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002896{
2897 CommandObject::CommandMap::const_iterator pos;
2898
Jim Inghamaf3753e2013-05-17 01:30:37 +00002899 if (search_builtin_commands)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002900 {
Jim Inghamaf3753e2013-05-17 01:30:37 +00002901 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002902 {
Jim Inghamaf3753e2013-05-17 01:30:37 +00002903 const char *command_name = pos->first.c_str();
2904 CommandObject *cmd_obj = pos->second.get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002905
Jim Inghamaf3753e2013-05-17 01:30:37 +00002906 if (cmd_obj->HelpTextContainsWord (search_word))
2907 {
2908 commands_found.AppendString (command_name);
2909 commands_help.AppendString (cmd_obj->GetHelp());
2910 }
2911
2912 if (cmd_obj->IsMultiwordObject())
2913 cmd_obj->AproposAllSubCommands (command_name,
2914 search_word,
2915 commands_found,
2916 commands_help);
2917
2918 }
2919 }
2920
2921 if (search_user_commands)
2922 {
2923 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
2924 {
2925 const char *command_name = pos->first.c_str();
2926 CommandObject *cmd_obj = pos->second.get();
2927
2928 if (cmd_obj->HelpTextContainsWord (search_word))
2929 {
2930 commands_found.AppendString (command_name);
2931 commands_help.AppendString (cmd_obj->GetHelp());
2932 }
2933
2934 if (cmd_obj->IsMultiwordObject())
2935 cmd_obj->AproposAllSubCommands (command_name,
2936 search_word,
2937 commands_found,
2938 commands_help);
2939
2940 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002941 }
2942}
Greg Clayton8b82f082011-04-12 05:54:46 +00002943
Greg Clayton8b82f082011-04-12 05:54:46 +00002944void
2945CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
2946{
Ed Masted78c9572014-04-20 00:31:37 +00002947 if (override_context != nullptr)
Greg Clayton8b82f082011-04-12 05:54:46 +00002948 {
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00002949 m_exe_ctx_ref = *override_context;
Greg Clayton8b82f082011-04-12 05:54:46 +00002950 }
2951 else
2952 {
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00002953 const bool adopt_selected = true;
2954 m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
Greg Clayton8b82f082011-04-12 05:54:46 +00002955 }
2956}
Greg Clayton44d93782014-01-27 23:43:24 +00002957
2958
2959size_t
2960CommandInterpreter::GetProcessOutput ()
2961{
2962 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
2963 char stdio_buffer[1024];
2964 size_t len;
2965 size_t total_bytes = 0;
2966 Error error;
2967 TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
2968 if (target_sp)
2969 {
2970 ProcessSP process_sp (target_sp->GetProcessSP());
2971 if (process_sp)
2972 {
2973 while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
2974 {
2975 size_t bytes_written = len;
2976 m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written);
2977 total_bytes += len;
2978 }
2979 while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
2980 {
2981 size_t bytes_written = len;
2982 m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written);
2983 total_bytes += len;
2984 }
2985 }
2986 }
2987 return total_bytes;
2988}
2989
2990void
2991CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
2992{
Greg Clayton340b0302014-02-05 17:57:57 +00002993 const bool is_interactive = io_handler.GetIsInteractive();
2994 if (is_interactive == false)
2995 {
2996 // When we are not interactive, don't execute blank lines. This will happen
2997 // sourcing a commands file. We don't want blank lines to repeat the previous
2998 // command and cause any errors to occur (like redefining an alias, get an error
2999 // and stop parsing the commands file).
3000 if (line.empty())
3001 return;
3002
3003 // When using a non-interactive file handle (like when sourcing commands from a file)
3004 // we need to echo the command out so we don't just see the command output and no
3005 // command...
3006 if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
3007 io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
3008 }
3009
Greg Clayton44d93782014-01-27 23:43:24 +00003010 lldb_private::CommandReturnObject result;
3011 HandleCommand(line.c_str(), eLazyBoolCalculate, result);
3012
Greg Clayton44d93782014-01-27 23:43:24 +00003013 // Now emit the command output text from the command we just executed
Greg Clayton340b0302014-02-05 17:57:57 +00003014 if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult))
3015 {
3016 // Display any STDOUT/STDERR _prior_ to emitting the command result text
3017 GetProcessOutput ();
3018
Greg Clayton8ee67312014-02-05 21:46:20 +00003019 if (!result.GetImmediateOutputStream())
3020 {
3021 const char *output = result.GetOutputData();
3022 if (output && output[0])
3023 io_handler.GetOutputStreamFile()->PutCString(output);
3024 }
Greg Clayton44d93782014-01-27 23:43:24 +00003025
Greg Clayton340b0302014-02-05 17:57:57 +00003026 // Now emit the command error text from the command we just executed
Greg Clayton8ee67312014-02-05 21:46:20 +00003027 if (!result.GetImmediateErrorStream())
3028 {
3029 const char *error = result.GetErrorData();
3030 if (error && error[0])
3031 io_handler.GetErrorStreamFile()->PutCString(error);
3032 }
Greg Clayton340b0302014-02-05 17:57:57 +00003033 }
Greg Clayton44d93782014-01-27 23:43:24 +00003034
3035 switch (result.GetStatus())
3036 {
3037 case eReturnStatusInvalid:
3038 case eReturnStatusSuccessFinishNoResult:
3039 case eReturnStatusSuccessFinishResult:
Greg Clayton340b0302014-02-05 17:57:57 +00003040 case eReturnStatusStarted:
3041 break;
3042
Greg Clayton44d93782014-01-27 23:43:24 +00003043 case eReturnStatusSuccessContinuingNoResult:
3044 case eReturnStatusSuccessContinuingResult:
Greg Clayton340b0302014-02-05 17:57:57 +00003045 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue))
3046 io_handler.SetIsDone(true);
3047 break;
3048
Greg Clayton44d93782014-01-27 23:43:24 +00003049 case eReturnStatusFailed:
Greg Clayton340b0302014-02-05 17:57:57 +00003050 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError))
3051 io_handler.SetIsDone(true);
Greg Clayton44d93782014-01-27 23:43:24 +00003052 break;
3053
3054 case eReturnStatusQuit:
3055 io_handler.SetIsDone(true);
3056 break;
3057 }
3058}
3059
Greg Claytonf0066ad2014-05-02 00:45:31 +00003060bool
3061CommandInterpreter::IOHandlerInterrupt (IOHandler &io_handler)
3062{
3063 ExecutionContext exe_ctx (GetExecutionContext());
3064 Process *process = exe_ctx.GetProcessPtr();
3065
3066 if (process)
3067 {
3068 StateType state = process->GetState();
3069 if (StateIsRunningState(state))
3070 {
3071 process->Halt();
3072 return true; // Don't do any updating when we are running
3073 }
3074 }
3075 return false;
3076}
3077
Greg Clayton44d93782014-01-27 23:43:24 +00003078void
3079CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,
3080 IOHandlerDelegate &delegate,
3081 bool asynchronously,
3082 void *baton)
3083{
3084 Debugger &debugger = GetDebugger();
3085 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
3086 "lldb", // Name of input reader for history
3087 prompt, // Prompt
3088 true, // Get multiple lines
Greg Claytonf6913cd2014-03-07 00:53:24 +00003089 0, // Don't show line numbers
Greg Clayton44d93782014-01-27 23:43:24 +00003090 delegate)); // IOHandlerDelegate
3091
3092 if (io_handler_sp)
3093 {
3094 io_handler_sp->SetUserData (baton);
3095 if (asynchronously)
3096 debugger.PushIOHandler(io_handler_sp);
3097 else
3098 debugger.RunIOHandler(io_handler_sp);
3099 }
3100
3101}
3102
3103
3104void
3105CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt,
3106 IOHandlerDelegate &delegate,
3107 bool asynchronously,
3108 void *baton)
3109{
3110 Debugger &debugger = GetDebugger();
3111 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
3112 "lldb-python", // Name of input reader for history
3113 prompt, // Prompt
3114 true, // Get multiple lines
Greg Claytonf6913cd2014-03-07 00:53:24 +00003115 0, // Don't show line numbers
Greg Clayton44d93782014-01-27 23:43:24 +00003116 delegate)); // IOHandlerDelegate
3117
3118 if (io_handler_sp)
3119 {
3120 io_handler_sp->SetUserData (baton);
3121 if (asynchronously)
3122 debugger.PushIOHandler(io_handler_sp);
3123 else
3124 debugger.RunIOHandler(io_handler_sp);
3125 }
3126
3127}
3128
3129bool
3130CommandInterpreter::IsActive ()
3131{
3132 return m_debugger.IsTopIOHandler (m_command_io_handler_sp);
3133}
3134
3135void
3136CommandInterpreter::RunCommandInterpreter(bool auto_handle_events,
3137 bool spawn_thread)
3138{
3139 const bool multiple_lines = false; // Only get one line at a time
3140 if (!m_command_io_handler_sp)
3141 m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger,
3142 m_debugger.GetInputFile(),
3143 m_debugger.GetOutputFile(),
3144 m_debugger.GetErrorFile(),
Greg Clayton340b0302014-02-05 17:57:57 +00003145 eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult,
Greg Clayton44d93782014-01-27 23:43:24 +00003146 "lldb",
3147 m_debugger.GetPrompt(),
3148 multiple_lines,
Greg Claytonf6913cd2014-03-07 00:53:24 +00003149 0, // Don't show line numbers
Greg Clayton44d93782014-01-27 23:43:24 +00003150 *this));
3151 m_debugger.PushIOHandler(m_command_io_handler_sp);
3152
3153 if (auto_handle_events)
3154 m_debugger.StartEventHandlerThread();
3155
3156 if (spawn_thread)
3157 {
3158 m_debugger.StartIOHandlerThread();
3159 }
3160 else
3161 {
3162 m_debugger.ExecuteIOHanders();
3163
3164 if (auto_handle_events)
3165 m_debugger.StopEventHandlerThread();
3166 }
3167
3168}
3169