blob: 3dc5d29231879036434d491268de37902867681d [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
15#include <getopt.h>
16#include <stdlib.h>
17
Greg Clayton4a33d312011-06-23 17:59:56 +000018#include "CommandObjectScript.h"
Peter Collingbourne08405b62011-06-23 20:37:26 +000019#include "lldb/Interpreter/CommandObjectRegexCommand.h"
Greg Clayton4a33d312011-06-23 17:59:56 +000020
Eli Friedman3afb70c2010-06-13 02:17:17 +000021#include "../Commands/CommandObjectApropos.h"
22#include "../Commands/CommandObjectArgs.h"
23#include "../Commands/CommandObjectBreakpoint.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000024#include "../Commands/CommandObjectDisassemble.h"
25#include "../Commands/CommandObjectExpression.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000026#include "../Commands/CommandObjectFrame.h"
27#include "../Commands/CommandObjectHelp.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000028#include "../Commands/CommandObjectLog.h"
29#include "../Commands/CommandObjectMemory.h"
Greg Claytonded470d2011-03-19 01:12:21 +000030#include "../Commands/CommandObjectPlatform.h"
Enrico Granata21dfcd92012-09-28 23:57:51 +000031#include "../Commands/CommandObjectPlugin.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000032#include "../Commands/CommandObjectProcess.h"
33#include "../Commands/CommandObjectQuit.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000034#include "../Commands/CommandObjectRegister.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000035#include "../Commands/CommandObjectSettings.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000036#include "../Commands/CommandObjectSource.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000037#include "../Commands/CommandObjectCommands.h"
Eli Friedman3afb70c2010-06-13 02:17:17 +000038#include "../Commands/CommandObjectSyntax.h"
39#include "../Commands/CommandObjectTarget.h"
40#include "../Commands/CommandObjectThread.h"
Greg Clayton4a33d312011-06-23 17:59:56 +000041#include "../Commands/CommandObjectType.h"
Johnny Chen31c39da2010-12-23 20:21:44 +000042#include "../Commands/CommandObjectVersion.h"
Johnny Chenf04ee932011-09-22 18:04:58 +000043#include "../Commands/CommandObjectWatchpoint.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044
Greg Clayton7d2ef162013-03-29 17:03:23 +000045
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046#include "lldb/Core/Debugger.h"
Jim Ingham97a6dc72010-10-04 19:49:29 +000047#include "lldb/Core/InputReader.h"
Enrico Granatab5887262012-10-29 21:18:03 +000048#include "lldb/Core/Log.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000049#include "lldb/Core/Stream.h"
50#include "lldb/Core/Timer.h"
Enrico Granatab5887262012-10-29 21:18:03 +000051
Greg Clayton7fb56d02011-02-01 01:31:41 +000052#include "lldb/Host/Host.h"
Enrico Granatab5887262012-10-29 21:18:03 +000053
54#include "lldb/Interpreter/Args.h"
Greg Clayton7d2ef162013-03-29 17:03:23 +000055#include "lldb/Interpreter/CommandCompletions.h"
Enrico Granatab5887262012-10-29 21:18:03 +000056#include "lldb/Interpreter/CommandInterpreter.h"
Greg Clayton7d2ef162013-03-29 17:03:23 +000057#include "lldb/Interpreter/CommandReturnObject.h"
Enrico Granatab5887262012-10-29 21:18:03 +000058#include "lldb/Interpreter/Options.h"
59#include "lldb/Interpreter/ScriptInterpreterNone.h"
60#include "lldb/Interpreter/ScriptInterpreterPython.h"
61
62
Chris Lattner30fdc8d2010-06-08 16:52:24 +000063#include "lldb/Target/Process.h"
64#include "lldb/Target/Thread.h"
65#include "lldb/Target/TargetList.h"
66
Enrico Granatab5887262012-10-29 21:18:03 +000067#include "lldb/Utility/CleanUp.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000068
69using namespace lldb;
70using namespace lldb_private;
71
Greg Clayton754a9362012-08-23 00:22:02 +000072
73static PropertyDefinition
74g_properties[] =
75{
76 { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, NULL, NULL, "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." },
Enrico Granatabcba2b22013-01-17 21:36:19 +000077 { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, NULL, NULL, "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." },
Enrico Granata012d4fc2013-06-11 01:26:35 +000078 { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will stop running a 'command source' script upon encountering an error." },
Greg Clayton754a9362012-08-23 00:22:02 +000079 { NULL , OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL }
80};
81
82enum
83{
Enrico Granatabcba2b22013-01-17 21:36:19 +000084 ePropertyExpandRegexAliases = 0,
Enrico Granata012d4fc2013-06-11 01:26:35 +000085 ePropertyPromptOnQuit = 1,
86 ePropertyStopCmdSourceOnError = 2
Greg Clayton754a9362012-08-23 00:22:02 +000087};
88
Jim Ingham4bddaeb2012-02-16 06:50:00 +000089ConstString &
90CommandInterpreter::GetStaticBroadcasterClass ()
91{
92 static ConstString class_name ("lldb.commandInterpreter");
93 return class_name;
94}
95
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096CommandInterpreter::CommandInterpreter
97(
Greg Clayton66111032010-06-23 01:19:29 +000098 Debugger &debugger,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000099 ScriptLanguage script_language,
Greg Clayton66111032010-06-23 01:19:29 +0000100 bool synchronous_execution
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101) :
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000102 Broadcaster (&debugger, "lldb.command-interpreter"),
Greg Clayton754a9362012-08-23 00:22:02 +0000103 Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
Greg Clayton66111032010-06-23 01:19:29 +0000104 m_debugger (debugger),
Greg Clayton6eee5aa2010-10-11 01:05:37 +0000105 m_synchronous_execution (synchronous_execution),
Caroline Tice2f88aad2011-01-14 00:29:16 +0000106 m_skip_lldbinit_files (false),
Jim Ingham16e0c682011-08-12 23:34:31 +0000107 m_skip_app_init_files (false),
Jim Inghame16c50a2011-02-18 00:54:25 +0000108 m_script_interpreter_ap (),
Caroline Ticed61c10b2011-06-16 16:27:19 +0000109 m_comment_char ('#'),
Johnny Chen4ac1d9e2012-08-09 22:06:10 +0000110 m_batch_command_mode (false),
Enrico Granata5f5ab602012-05-31 01:09:06 +0000111 m_truncation_warning(eNoTruncation),
112 m_command_source_depth (0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113{
Greg Clayton67cc0632012-08-22 17:17:09 +0000114 debugger.SetScriptLanguage (script_language);
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000115 SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
116 SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
Greg Clayton67cc0632012-08-22 17:17:09 +0000117 SetEventName (eBroadcastBitQuitCommandReceived, "quit");
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000118 CheckInWithManager ();
Greg Clayton754a9362012-08-23 00:22:02 +0000119 m_collection_sp->Initialize (g_properties);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120}
121
Greg Clayton754a9362012-08-23 00:22:02 +0000122bool
123CommandInterpreter::GetExpandRegexAliases () const
124{
125 const uint32_t idx = ePropertyExpandRegexAliases;
126 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
127}
128
Enrico Granatabcba2b22013-01-17 21:36:19 +0000129bool
130CommandInterpreter::GetPromptOnQuit () const
131{
132 const uint32_t idx = ePropertyPromptOnQuit;
133 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
134}
Greg Clayton754a9362012-08-23 00:22:02 +0000135
Enrico Granata012d4fc2013-06-11 01:26:35 +0000136bool
137CommandInterpreter::GetStopCmdSourceOnError () const
138{
139 const uint32_t idx = ePropertyStopCmdSourceOnError;
140 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
141}
142
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143void
144CommandInterpreter::Initialize ()
145{
146 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
147
148 CommandReturnObject result;
149
150 LoadCommandDictionary ();
151
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000152 // Set up some initial aliases.
Caroline Ticeca90c472011-05-06 21:37:15 +0000153 CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
154 if (cmd_obj_sp)
155 {
156 AddAlias ("q", cmd_obj_sp);
157 AddAlias ("exit", cmd_obj_sp);
158 }
Sean Callanan247e62a2012-05-04 23:15:02 +0000159
Johnny Chen6d675242012-08-24 18:15:45 +0000160 cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
Sean Callanan247e62a2012-05-04 23:15:02 +0000161 if (cmd_obj_sp)
162 {
163 AddAlias ("attach", cmd_obj_sp);
164 }
Caroline Ticeca90c472011-05-06 21:37:15 +0000165
Johnny Chen6d675242012-08-24 18:15:45 +0000166 cmd_obj_sp = GetCommandSPExact ("process detach",false);
167 if (cmd_obj_sp)
168 {
169 AddAlias ("detach", cmd_obj_sp);
170 }
171
Caroline Ticeca90c472011-05-06 21:37:15 +0000172 cmd_obj_sp = GetCommandSPExact ("process continue", false);
173 if (cmd_obj_sp)
174 {
175 AddAlias ("c", cmd_obj_sp);
176 AddAlias ("continue", cmd_obj_sp);
177 }
178
179 cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
180 if (cmd_obj_sp)
181 AddAlias ("b", cmd_obj_sp);
182
Jim Inghamca36cd12012-10-05 19:16:31 +0000183 cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
184 if (cmd_obj_sp)
185 AddAlias ("tbreak", cmd_obj_sp);
186
Caroline Ticeca90c472011-05-06 21:37:15 +0000187 cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
188 if (cmd_obj_sp)
Jason Molendaf385f122011-10-22 00:47:41 +0000189 {
190 AddAlias ("stepi", cmd_obj_sp);
Caroline Ticeca90c472011-05-06 21:37:15 +0000191 AddAlias ("si", cmd_obj_sp);
Jason Molendaf385f122011-10-22 00:47:41 +0000192 }
193
194 cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false);
195 if (cmd_obj_sp)
196 {
197 AddAlias ("nexti", cmd_obj_sp);
198 AddAlias ("ni", cmd_obj_sp);
199 }
Caroline Ticeca90c472011-05-06 21:37:15 +0000200
201 cmd_obj_sp = GetCommandSPExact ("thread step-in", false);
202 if (cmd_obj_sp)
203 {
204 AddAlias ("s", cmd_obj_sp);
205 AddAlias ("step", cmd_obj_sp);
206 }
207
208 cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
209 if (cmd_obj_sp)
210 {
211 AddAlias ("n", cmd_obj_sp);
212 AddAlias ("next", cmd_obj_sp);
213 }
214
215 cmd_obj_sp = GetCommandSPExact ("thread step-out", false);
216 if (cmd_obj_sp)
217 {
Caroline Ticeca90c472011-05-06 21:37:15 +0000218 AddAlias ("finish", cmd_obj_sp);
219 }
220
Jim Ingham6d6d1072011-12-02 01:12:59 +0000221 cmd_obj_sp = GetCommandSPExact ("frame select", false);
222 if (cmd_obj_sp)
223 {
224 AddAlias ("f", cmd_obj_sp);
225 }
226
Jim Inghamca36cd12012-10-05 19:16:31 +0000227 cmd_obj_sp = GetCommandSPExact ("thread select", false);
228 if (cmd_obj_sp)
229 {
230 AddAlias ("t", cmd_obj_sp);
231 }
232
Greg Clayton6bade322013-02-01 23:33:03 +0000233 cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
Caroline Ticeca90c472011-05-06 21:37:15 +0000234 if (cmd_obj_sp)
235 {
236 AddAlias ("l", cmd_obj_sp);
237 AddAlias ("list", cmd_obj_sp);
238 }
239
Greg Claytonef5651d2013-02-12 18:52:24 +0000240 cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
241 if (cmd_obj_sp)
242 {
243 AddAlias ("env", cmd_obj_sp);
244 }
245
Caroline Ticeca90c472011-05-06 21:37:15 +0000246 cmd_obj_sp = GetCommandSPExact ("memory read", false);
247 if (cmd_obj_sp)
248 AddAlias ("x", cmd_obj_sp);
249
250 cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
251 if (cmd_obj_sp)
252 AddAlias ("up", cmd_obj_sp);
253
254 cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
255 if (cmd_obj_sp)
256 AddAlias ("down", cmd_obj_sp);
257
Jason Molenda0c8e0062011-10-25 02:11:20 +0000258 cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
Jason Molendabc7748b2011-10-22 01:30:52 +0000259 if (cmd_obj_sp)
260 AddAlias ("display", cmd_obj_sp);
Jim Ingham7e18e422011-10-24 18:37:00 +0000261
262 cmd_obj_sp = GetCommandSPExact ("disassemble", false);
263 if (cmd_obj_sp)
264 AddAlias ("dis", cmd_obj_sp);
265
266 cmd_obj_sp = GetCommandSPExact ("disassemble", false);
267 if (cmd_obj_sp)
268 AddAlias ("di", cmd_obj_sp);
269
270
Jason Molendabc7748b2011-10-22 01:30:52 +0000271
Jason Molenda0c8e0062011-10-25 02:11:20 +0000272 cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
Jason Molendabc7748b2011-10-22 01:30:52 +0000273 if (cmd_obj_sp)
274 AddAlias ("undisplay", cmd_obj_sp);
275
Jim Ingham71bf2992012-10-10 16:51:31 +0000276 cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
277 if (cmd_obj_sp)
278 AddAlias ("bt", cmd_obj_sp);
279
Caroline Ticeca90c472011-05-06 21:37:15 +0000280 cmd_obj_sp = GetCommandSPExact ("target create", false);
281 if (cmd_obj_sp)
282 AddAlias ("file", cmd_obj_sp);
283
284 cmd_obj_sp = GetCommandSPExact ("target modules", false);
285 if (cmd_obj_sp)
286 AddAlias ("image", cmd_obj_sp);
287
288
289 OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
Jim Inghamffba2292011-03-22 02:29:32 +0000290
Caroline Ticeca90c472011-05-06 21:37:15 +0000291 cmd_obj_sp = GetCommandSPExact ("expression", false);
292 if (cmd_obj_sp)
Sean Callanan90e579f2013-04-17 17:23:58 +0000293 {
Caroline Ticeca90c472011-05-06 21:37:15 +0000294 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
295 AddAlias ("p", cmd_obj_sp);
296 AddAlias ("print", cmd_obj_sp);
Sean Callanan316d5e42012-08-08 01:30:34 +0000297 AddAlias ("call", cmd_obj_sp);
Caroline Ticeca90c472011-05-06 21:37:15 +0000298 AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp);
299 AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp);
Sean Callanan316d5e42012-08-08 01:30:34 +0000300 AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp);
Caroline Ticeca90c472011-05-06 21:37:15 +0000301
302 alias_arguments_vector_sp.reset (new OptionArgVector);
Greg Clayton9e57dcd2013-05-15 01:03:08 +0000303 ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp);
Caroline Ticeca90c472011-05-06 21:37:15 +0000304 AddAlias ("po", cmd_obj_sp);
305 AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
306 }
307
Sean Callanan2e1d9ba2012-06-01 23:29:32 +0000308 cmd_obj_sp = GetCommandSPExact ("process kill", false);
309 if (cmd_obj_sp)
Greg Claytone86fd742012-09-27 00:02:27 +0000310 {
Sean Callanan2e1d9ba2012-06-01 23:29:32 +0000311 AddAlias ("kill", cmd_obj_sp);
Greg Claytone86fd742012-09-27 00:02:27 +0000312 }
Sean Callanan2e1d9ba2012-06-01 23:29:32 +0000313
Caroline Ticeca90c472011-05-06 21:37:15 +0000314 cmd_obj_sp = GetCommandSPExact ("process launch", false);
315 if (cmd_obj_sp)
316 {
317 alias_arguments_vector_sp.reset (new OptionArgVector);
Jason Molenda85da3122012-07-06 02:46:23 +0000318#if defined (__arm__)
319 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
320#else
Greg Clayton0ca92a12012-05-18 00:04:38 +0000321 ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=/bin/bash --", alias_arguments_vector_sp);
Jason Molenda85da3122012-07-06 02:46:23 +0000322#endif
Caroline Ticeca90c472011-05-06 21:37:15 +0000323 AddAlias ("r", cmd_obj_sp);
324 AddAlias ("run", cmd_obj_sp);
325 AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp);
326 AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp);
327 }
Greg Clayton843d62d2012-03-29 21:47:51 +0000328
329 cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
330 if (cmd_obj_sp)
331 {
332 AddAlias ("add-dsym", cmd_obj_sp);
333 }
Sean Callananfc732752012-05-21 18:25:19 +0000334
335 cmd_obj_sp = GetCommandSPExact ("breakpoint set", false);
336 if (cmd_obj_sp)
337 {
338 alias_arguments_vector_sp.reset (new OptionArgVector);
339 ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp);
Jim Ingham06d282d2012-10-18 23:24:12 +0000340 AddAlias ("rbreak", cmd_obj_sp);
341 AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp);
Sean Callananfc732752012-05-21 18:25:19 +0000342 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000343}
344
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000345const char *
346CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
347{
348 // This function has not yet been implemented.
349
350 // Look for any embedded script command
351 // If found,
352 // get interpreter object from the command dictionary,
353 // call execute_one_command on it,
354 // get the results as a string,
355 // substitute that string for current stuff.
356
357 return arg;
358}
359
360
361void
362CommandInterpreter::LoadCommandDictionary ()
363{
364 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
365
Caroline Ticedaccaa92010-09-20 20:44:43 +0000366 lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000367
Greg Claytona7015092010-09-18 01:14:36 +0000368 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000369 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
Johnny Chenb89982d2011-04-21 00:39:18 +0000370 m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
Greg Claytona7015092010-09-18 01:14:36 +0000371 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
372 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000373 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
Greg Claytona7015092010-09-18 01:14:36 +0000374 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000375 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this));
376 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this));
Greg Claytonded470d2011-03-19 01:12:21 +0000377 m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this));
Enrico Granata21dfcd92012-09-28 23:57:51 +0000378 m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000379 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
Greg Claytona7015092010-09-18 01:14:36 +0000380 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000381 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this));
Greg Claytona7015092010-09-18 01:14:36 +0000382 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language));
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000383 m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
Jim Inghamebc09c32010-07-07 03:36:20 +0000384 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this));
Greg Clayton66111032010-06-23 01:19:29 +0000385 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
386 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this));
Enrico Granata223383e2011-08-16 23:24:13 +0000387 m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this));
Johnny Chen31c39da2010-12-23 20:21:44 +0000388 m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this));
Johnny Chenf04ee932011-09-22 18:04:58 +0000389 m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390
Jim Inghamca36cd12012-10-05 19:16:31 +0000391 const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
392 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
Greg Clayton722e8852013-02-08 02:54:24 +0000393 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
Greg Clayton1b3815c2013-01-30 00:18:29 +0000394 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
Jim Inghamca36cd12012-10-05 19:16:31 +0000395 {"^(-.*)$", "breakpoint set %1"},
396 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
Greg Clayton722e8852013-02-08 02:54:24 +0000397 {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"},
Jim Inghamca36cd12012-10-05 19:16:31 +0000398 {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}};
399
400 size_t num_regexes = sizeof break_regexes/sizeof(char *[2]);
401
Greg Clayton7b0992d2013-04-18 22:45:39 +0000402 std::unique_ptr<CommandObjectRegexCommand>
Greg Claytona7015092010-09-18 01:14:36 +0000403 break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton8b82f082011-04-12 05:54:46 +0000404 "_regexp-break",
Johnny Chenb417dcd2012-08-23 00:32:22 +0000405 "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 +0000406 "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
407 2,
408 CommandCompletions::eSymbolCompletion |
409 CommandCompletions::eSourceFileCompletion));
Jim Inghamca36cd12012-10-05 19:16:31 +0000410
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000411 if (break_regex_cmd_ap.get())
412 {
Jim Inghamca36cd12012-10-05 19:16:31 +0000413 bool success = true;
414 for (size_t i = 0; i < num_regexes; i++)
415 {
416 success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]);
417 if (!success)
418 break;
419 }
420 success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
421
422 if (success)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000423 {
424 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
425 m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
426 }
427 }
Jim Inghamffba2292011-03-22 02:29:32 +0000428
Greg Clayton7b0992d2013-04-18 22:45:39 +0000429 std::unique_ptr<CommandObjectRegexCommand>
Jim Inghamca36cd12012-10-05 19:16:31 +0000430 tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this,
431 "_regexp-tbreak",
432 "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 +0000433 "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
434 2,
435 CommandCompletions::eSymbolCompletion |
436 CommandCompletions::eSourceFileCompletion));
Jim Inghamca36cd12012-10-05 19:16:31 +0000437
438 if (tbreak_regex_cmd_ap.get())
439 {
440 bool success = true;
441 for (size_t i = 0; i < num_regexes; i++)
442 {
443 // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
444 char buffer[1024];
445 int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
446 assert (num_printed < 1024);
447 success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
448 if (!success)
449 break;
450 }
451 success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
452
453 if (success)
454 {
455 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
456 m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp;
457 }
458 }
459
Greg Clayton7b0992d2013-04-18 22:45:39 +0000460 std::unique_ptr<CommandObjectRegexCommand>
Johnny Chen6d675242012-08-24 18:15:45 +0000461 attach_regex_cmd_ap(new CommandObjectRegexCommand (*this,
462 "_regexp-attach",
463 "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 +0000464 "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]",
465 2));
Johnny Chen6d675242012-08-24 18:15:45 +0000466 if (attach_regex_cmd_ap.get())
467 {
Greg Clayton3cb4c7d2012-12-15 01:19:07 +0000468 if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") &&
469 attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach'
470 attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") &&
471 attach_regex_cmd_ap->AddRegexCommand("^$", "process attach"))
Johnny Chen6d675242012-08-24 18:15:45 +0000472 {
473 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release());
474 m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp;
475 }
476 }
477
Greg Clayton7b0992d2013-04-18 22:45:39 +0000478 std::unique_ptr<CommandObjectRegexCommand>
Jim Inghamffba2292011-03-22 02:29:32 +0000479 down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton8b82f082011-04-12 05:54:46 +0000480 "_regexp-down",
481 "Go down \"n\" frames in the stack (1 frame by default).",
482 "_regexp-down [n]", 2));
Jim Inghamffba2292011-03-22 02:29:32 +0000483 if (down_regex_cmd_ap.get())
484 {
485 if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
486 down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1"))
487 {
488 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
489 m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
490 }
491 }
492
Greg Clayton7b0992d2013-04-18 22:45:39 +0000493 std::unique_ptr<CommandObjectRegexCommand>
Jim Inghamffba2292011-03-22 02:29:32 +0000494 up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton8b82f082011-04-12 05:54:46 +0000495 "_regexp-up",
496 "Go up \"n\" frames in the stack (1 frame by default).",
497 "_regexp-up [n]", 2));
Jim Inghamffba2292011-03-22 02:29:32 +0000498 if (up_regex_cmd_ap.get())
499 {
500 if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
501 up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1"))
502 {
503 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
504 m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp;
505 }
506 }
Jason Molendabc7748b2011-10-22 01:30:52 +0000507
Greg Clayton7b0992d2013-04-18 22:45:39 +0000508 std::unique_ptr<CommandObjectRegexCommand>
Jason Molendabc7748b2011-10-22 01:30:52 +0000509 display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton7d2ef162013-03-29 17:03:23 +0000510 "_regexp-display",
511 "Add an expression evaluation stop-hook.",
512 "_regexp-display expression", 2));
Jason Molendabc7748b2011-10-22 01:30:52 +0000513 if (display_regex_cmd_ap.get())
514 {
515 if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
516 {
517 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release());
518 m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp;
519 }
520 }
521
Greg Clayton7b0992d2013-04-18 22:45:39 +0000522 std::unique_ptr<CommandObjectRegexCommand>
Jason Molendabc7748b2011-10-22 01:30:52 +0000523 undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton7d2ef162013-03-29 17:03:23 +0000524 "_regexp-undisplay",
525 "Remove an expression evaluation stop-hook.",
526 "_regexp-undisplay stop-hook-number", 2));
Jason Molendabc7748b2011-10-22 01:30:52 +0000527 if (undisplay_regex_cmd_ap.get())
528 {
529 if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
530 {
531 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release());
532 m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp;
533 }
534 }
535
Greg Clayton7b0992d2013-04-18 22:45:39 +0000536 std::unique_ptr<CommandObjectRegexCommand>
Greg Clayton30c0a1c2012-09-26 22:26:47 +0000537 connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton7d2ef162013-03-29 17:03:23 +0000538 "gdb-remote",
539 "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.",
540 "gdb-remote [<hostname>:]<portnum>", 2));
Greg Clayton30c0a1c2012-09-26 22:26:47 +0000541 if (connect_gdb_remote_cmd_ap.get())
542 {
543 if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") &&
544 connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1"))
545 {
546 CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release());
547 m_command_dict[command_sp->GetCommandName ()] = command_sp;
548 }
549 }
550
Greg Clayton7b0992d2013-04-18 22:45:39 +0000551 std::unique_ptr<CommandObjectRegexCommand>
Greg Clayton30c0a1c2012-09-26 22:26:47 +0000552 connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this,
553 "kdp-remote",
Jason Molendaa7dcb332012-10-23 03:05:16 +0000554 "Connect to a remote KDP server. udp port 41139 is the default port number.",
555 "kdp-remote <hostname>[:<portnum>]", 2));
Greg Clayton30c0a1c2012-09-26 22:26:47 +0000556 if (connect_kdp_remote_cmd_ap.get())
557 {
558 if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
Jason Molendac36b1842012-09-27 02:47:55 +0000559 connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139"))
Greg Clayton30c0a1c2012-09-26 22:26:47 +0000560 {
561 CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
562 m_command_dict[command_sp->GetCommandName ()] = command_sp;
563 }
564 }
565
Greg Clayton7b0992d2013-04-18 22:45:39 +0000566 std::unique_ptr<CommandObjectRegexCommand>
Jason Molenda4cddfed2012-10-05 05:29:32 +0000567 bt_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Jim Ingham71bf2992012-10-10 16:51:31 +0000568 "_regexp-bt",
Jason Molenda4cddfed2012-10-05 05:29:32 +0000569 "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.",
570 "bt [<digit>|all]", 2));
571 if (bt_regex_cmd_ap.get())
572 {
573 // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
574 // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and
575 // so now "bt 3" is the preferred form, in line with gdb.
576 if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") &&
577 bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") &&
578 bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") &&
579 bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace"))
580 {
581 CommandObjectSP command_sp(bt_regex_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>
Greg Clayton6bade322013-02-01 23:33:03 +0000587 list_regex_cmd_ap(new CommandObjectRegexCommand (*this,
588 "_regexp-list",
589 "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.",
Greg Clayton7d2ef162013-03-29 17:03:23 +0000590 "_regexp-list [<line>]\n_regexp-attach [<file>:<line>]\n_regexp-attach [<file>:<line>]",
591 2,
592 CommandCompletions::eSourceFileCompletion));
Greg Clayton6bade322013-02-01 23:33:03 +0000593 if (list_regex_cmd_ap.get())
594 {
595 if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") &&
596 list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") &&
597 list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") &&
Greg Claytond9010962013-02-12 18:42:05 +0000598 list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") &&
Greg Claytone4ca5152013-03-13 18:25:49 +0000599 list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") &&
Greg Clayton6bade322013-02-01 23:33:03 +0000600 list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") &&
601 list_regex_cmd_ap->AddRegexCommand("^$", "source list"))
602 {
603 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release());
604 m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp;
605 }
606 }
607
Greg Clayton7b0992d2013-04-18 22:45:39 +0000608 std::unique_ptr<CommandObjectRegexCommand>
Greg Claytonef5651d2013-02-12 18:52:24 +0000609 env_regex_cmd_ap(new CommandObjectRegexCommand (*this,
Greg Clayton7d2ef162013-03-29 17:03:23 +0000610 "_regexp-env",
611 "Implements a shortcut to viewing and setting environment variables.",
612 "_regexp-env\n_regexp-env FOO=BAR", 2));
Greg Claytonef5651d2013-02-12 18:52:24 +0000613 if (env_regex_cmd_ap.get())
614 {
615 if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") &&
616 env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1"))
617 {
618 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release());
619 m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp;
620 }
621 }
622
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000623}
624
625int
626CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
627 StringList &matches)
628{
629 CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
630
631 if (include_aliases)
632 {
633 CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
634 }
635
636 return matches.GetSize();
637}
638
639CommandObjectSP
640CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
641{
642 CommandObject::CommandMap::iterator pos;
Greg Claytonc7bece562013-01-25 18:06:21 +0000643 CommandObjectSP command_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000644
645 std::string cmd(cmd_cstr);
646
647 if (HasCommands())
648 {
649 pos = m_command_dict.find(cmd);
650 if (pos != m_command_dict.end())
Greg Claytonc7bece562013-01-25 18:06:21 +0000651 command_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000652 }
653
654 if (include_aliases && HasAliases())
655 {
656 pos = m_alias_dict.find(cmd);
657 if (pos != m_alias_dict.end())
Greg Claytonc7bece562013-01-25 18:06:21 +0000658 command_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000659 }
660
661 if (HasUserCommands())
662 {
663 pos = m_user_dict.find(cmd);
664 if (pos != m_user_dict.end())
Greg Claytonc7bece562013-01-25 18:06:21 +0000665 command_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000666 }
667
Greg Claytonc7bece562013-01-25 18:06:21 +0000668 if (!exact && !command_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000669 {
Jim Ingham279a6c22010-07-06 22:46:59 +0000670 // We will only get into here if we didn't find any exact matches.
671
672 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
673
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000674 StringList local_matches;
675 if (matches == NULL)
676 matches = &local_matches;
677
Jim Ingham279a6c22010-07-06 22:46:59 +0000678 unsigned int num_cmd_matches = 0;
679 unsigned int num_alias_matches = 0;
680 unsigned int num_user_matches = 0;
681
682 // Look through the command dictionaries one by one, and if we get only one match from any of
683 // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
684
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000685 if (HasCommands())
686 {
687 num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
688 }
689
690 if (num_cmd_matches == 1)
691 {
692 cmd.assign(matches->GetStringAtIndex(0));
693 pos = m_command_dict.find(cmd);
694 if (pos != m_command_dict.end())
Jim Ingham279a6c22010-07-06 22:46:59 +0000695 real_match_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000696 }
697
Jim Ingham490ac552010-06-24 20:28:42 +0000698 if (include_aliases && HasAliases())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000699 {
700 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
701
702 }
703
Jim Ingham279a6c22010-07-06 22:46:59 +0000704 if (num_alias_matches == 1)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000705 {
706 cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
707 pos = m_alias_dict.find(cmd);
708 if (pos != m_alias_dict.end())
Jim Ingham279a6c22010-07-06 22:46:59 +0000709 alias_match_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000710 }
711
Jim Ingham490ac552010-06-24 20:28:42 +0000712 if (HasUserCommands())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000713 {
714 num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
715 }
716
Jim Ingham279a6c22010-07-06 22:46:59 +0000717 if (num_user_matches == 1)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000718 {
719 cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
720
721 pos = m_user_dict.find (cmd);
722 if (pos != m_user_dict.end())
Jim Ingham279a6c22010-07-06 22:46:59 +0000723 user_match_sp = pos->second;
724 }
725
726 // If we got exactly one match, return that, otherwise return the match list.
727
728 if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
729 {
730 if (num_cmd_matches)
731 return real_match_sp;
732 else if (num_alias_matches)
733 return alias_match_sp;
734 else
735 return user_match_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000736 }
737 }
Greg Claytonc7bece562013-01-25 18:06:21 +0000738 else if (matches && command_sp)
Jim Ingham279a6c22010-07-06 22:46:59 +0000739 {
740 matches->AppendString (cmd_cstr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000741 }
742
743
Greg Claytonc7bece562013-01-25 18:06:21 +0000744 return command_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000745}
746
Greg Claytonde164aa2011-04-20 16:37:46 +0000747bool
748CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
749{
750 if (name && name[0])
751 {
752 std::string name_sstr(name);
Enrico Granatae00af802012-10-01 17:19:37 +0000753 bool found = (m_command_dict.find (name_sstr) != m_command_dict.end());
754 if (found && !can_replace)
755 return false;
756 if (found && m_command_dict[name_sstr]->IsRemovable() == false)
Enrico Granata21dfcd92012-09-28 23:57:51 +0000757 return false;
Greg Claytonde164aa2011-04-20 16:37:46 +0000758 m_command_dict[name_sstr] = cmd_sp;
759 return true;
760 }
761 return false;
762}
763
Enrico Granata223383e2011-08-16 23:24:13 +0000764bool
Enrico Granata0a305db2011-11-07 22:57:04 +0000765CommandInterpreter::AddUserCommand (std::string name,
Enrico Granata223383e2011-08-16 23:24:13 +0000766 const lldb::CommandObjectSP &cmd_sp,
767 bool can_replace)
768{
Enrico Granata0a305db2011-11-07 22:57:04 +0000769 if (!name.empty())
Enrico Granata223383e2011-08-16 23:24:13 +0000770 {
Enrico Granata0a305db2011-11-07 22:57:04 +0000771
772 const char* name_cstr = name.c_str();
773
774 // do not allow replacement of internal commands
775 if (CommandExists(name_cstr))
Enrico Granata21dfcd92012-09-28 23:57:51 +0000776 {
777 if (can_replace == false)
778 return false;
779 if (m_command_dict[name]->IsRemovable() == false)
780 return false;
781 }
Enrico Granata0a305db2011-11-07 22:57:04 +0000782
Enrico Granata21dfcd92012-09-28 23:57:51 +0000783 if (UserCommandExists(name_cstr))
784 {
785 if (can_replace == false)
786 return false;
787 if (m_user_dict[name]->IsRemovable() == false)
788 return false;
789 }
790
Enrico Granata0a305db2011-11-07 22:57:04 +0000791 m_user_dict[name] = cmd_sp;
Enrico Granata223383e2011-08-16 23:24:13 +0000792 return true;
793 }
794 return false;
795}
Greg Claytonde164aa2011-04-20 16:37:46 +0000796
Jim Ingham279a6c22010-07-06 22:46:59 +0000797CommandObjectSP
798CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000799{
Caroline Tice472362e2010-12-14 18:51:39 +0000800 Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
801 CommandObjectSP ret_val; // Possibly empty return value.
802
803 if (cmd_cstr == NULL)
804 return ret_val;
805
806 if (cmd_words.GetArgumentCount() == 1)
807 return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
808 else
809 {
810 // We have a multi-word command (seemingly), so we need to do more work.
811 // First, get the cmd_obj_sp for the first word in the command.
812 CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL);
813 if (cmd_obj_sp.get() != NULL)
814 {
815 // Loop through the rest of the words in the command (everything passed in was supposed to be part of a
816 // command name), and find the appropriate sub-command SP for each command word....
817 size_t end = cmd_words.GetArgumentCount();
818 for (size_t j= 1; j < end; ++j)
819 {
820 if (cmd_obj_sp->IsMultiwordObject())
821 {
Greg Clayton998255b2012-10-13 02:07:45 +0000822 cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
Caroline Tice472362e2010-12-14 18:51:39 +0000823 if (cmd_obj_sp.get() == NULL)
824 // The sub-command name was invalid. Fail and return the empty 'ret_val'.
825 return ret_val;
826 }
827 else
828 // We have more words in the command name, but we don't have a multiword object. Fail and return
829 // empty 'ret_val'.
830 return ret_val;
831 }
832 // We successfully looped through all the command words and got valid command objects for them. Assign the
833 // last object retrieved to 'ret_val'.
834 ret_val = cmd_obj_sp;
835 }
836 }
837 return ret_val;
Jim Ingham279a6c22010-07-06 22:46:59 +0000838}
839
840CommandObject *
841CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
842{
843 return GetCommandSPExact (cmd_cstr, include_aliases).get();
844}
845
846CommandObject *
847CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
848{
849 CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
850
851 // If we didn't find an exact match to the command string in the commands, look in
852 // the aliases.
853
854 if (command_obj == NULL)
855 {
856 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
857 }
858
Matt Kopec038ff812013-04-23 16:17:32 +0000859 // If there wasn't an exact match among the aliases, look for an inexact match
860 // in just the commands.
Jim Ingham279a6c22010-07-06 22:46:59 +0000861
862 if (command_obj == NULL)
Matt Kopec038ff812013-04-23 16:17:32 +0000863 command_obj = GetCommandSP(cmd_cstr, false, false, matches).get();
864
865 // Finally, if there wasn't an inexact match among the commands, look for an inexact
866 // match in both the commands and aliases.
867 if (command_obj == NULL)
Jim Ingham279a6c22010-07-06 22:46:59 +0000868 command_obj = GetCommandSP(cmd_cstr, true, false, matches).get();
869
870 return command_obj;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000871}
872
873bool
874CommandInterpreter::CommandExists (const char *cmd)
875{
876 return m_command_dict.find(cmd) != m_command_dict.end();
877}
878
879bool
Caroline Ticeca90c472011-05-06 21:37:15 +0000880CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
881 const char *options_args,
882 OptionArgVectorSP &option_arg_vector_sp)
883{
884 bool success = true;
885 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
886
887 if (!options_args || (strlen (options_args) < 1))
888 return true;
889
890 std::string options_string (options_args);
891 Args args (options_args);
892 CommandReturnObject result;
893 // Check to see if the command being aliased can take any command options.
894 Options *options = cmd_obj_sp->GetOptions ();
895 if (options)
896 {
897 // See if any options were specified as part of the alias; if so, handle them appropriately.
898 options->NotifyOptionParsingStarting ();
899 args.Unshift ("dummy_arg");
900 args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
901 args.Shift ();
902 if (result.Succeeded())
903 options->VerifyPartialOptions (result);
904 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
905 {
906 result.AppendError ("Unable to create requested alias.\n");
907 return false;
908 }
909 }
910
Greg Clayton5521f992011-10-28 21:38:01 +0000911 if (!options_string.empty())
Caroline Ticeca90c472011-05-06 21:37:15 +0000912 {
913 if (cmd_obj_sp->WantsRawCommandString ())
914 option_arg_vector->push_back (OptionArgPair ("<argument>",
915 OptionArgValue (-1,
916 options_string)));
917 else
918 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000919 const size_t argc = args.GetArgumentCount();
Caroline Ticeca90c472011-05-06 21:37:15 +0000920 for (size_t i = 0; i < argc; ++i)
921 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
922 option_arg_vector->push_back
923 (OptionArgPair ("<argument>",
924 OptionArgValue (-1,
925 std::string (args.GetArgumentAtIndex (i)))));
926 }
927 }
928
929 return success;
930}
931
932bool
Jim Ingham298f3782013-04-03 00:25:49 +0000933CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
934{
935 bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end());
936 if (exact_match)
937 {
938 full_name.assign(cmd);
939 return exact_match;
940 }
941 else
942 {
943 StringList matches;
944 size_t num_alias_matches;
945 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
946 if (num_alias_matches == 1)
947 {
948 // Make sure this isn't shadowing a command in the regular command space:
949 StringList regular_matches;
950 const bool include_aliases = false;
951 const bool exact = false;
952 CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, &regular_matches));
953 if (cmd_obj_sp || regular_matches.GetSize() > 0)
954 return false;
955 else
956 {
957 full_name.assign (matches.GetStringAtIndex(0));
958 return true;
959 }
960 }
961 else
962 return false;
963 }
964}
965
966bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000967CommandInterpreter::AliasExists (const char *cmd)
968{
969 return m_alias_dict.find(cmd) != m_alias_dict.end();
970}
971
972bool
973CommandInterpreter::UserCommandExists (const char *cmd)
974{
975 return m_user_dict.find(cmd) != m_user_dict.end();
976}
977
978void
979CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
980{
Jim Ingham279a6c22010-07-06 22:46:59 +0000981 command_obj_sp->SetIsAlias (true);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000982 m_alias_dict[alias_name] = command_obj_sp;
983}
984
985bool
986CommandInterpreter::RemoveAlias (const char *alias_name)
987{
988 CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
989 if (pos != m_alias_dict.end())
990 {
991 m_alias_dict.erase(pos);
992 return true;
993 }
994 return false;
995}
996bool
997CommandInterpreter::RemoveUser (const char *alias_name)
998{
999 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
1000 if (pos != m_user_dict.end())
1001 {
1002 m_user_dict.erase(pos);
1003 return true;
1004 }
1005 return false;
1006}
1007
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001008void
1009CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
1010{
1011 help_string.Printf ("'%s", command_name);
1012 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1013
Sean Callanan9a028512012-08-09 00:50:26 +00001014 if (option_arg_vector_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001015 {
1016 OptionArgVector *options = option_arg_vector_sp.get();
1017 for (int i = 0; i < options->size(); ++i)
1018 {
1019 OptionArgPair cur_option = (*options)[i];
1020 std::string opt = cur_option.first;
Caroline Ticed9d63362010-12-07 19:58:26 +00001021 OptionArgValue value_pair = cur_option.second;
1022 std::string value = value_pair.second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001023 if (opt.compare("<argument>") == 0)
1024 {
1025 help_string.Printf (" %s", value.c_str());
1026 }
1027 else
1028 {
1029 help_string.Printf (" %s", opt.c_str());
1030 if ((value.compare ("<no-argument>") != 0)
1031 && (value.compare ("<need-argument") != 0))
1032 {
1033 help_string.Printf (" %s", value.c_str());
1034 }
1035 }
1036 }
1037 }
1038
1039 help_string.Printf ("'");
1040}
1041
Greg Clayton12fc3e02010-08-26 22:05:43 +00001042size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001043CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
1044{
1045 CommandObject::CommandMap::const_iterator pos;
Greg Clayton12fc3e02010-08-26 22:05:43 +00001046 CommandObject::CommandMap::const_iterator end = dict.end();
1047 size_t max_len = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001048
Greg Clayton12fc3e02010-08-26 22:05:43 +00001049 for (pos = dict.begin(); pos != end; ++pos)
1050 {
1051 size_t len = pos->first.size();
1052 if (max_len < len)
1053 max_len = len;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001054 }
Greg Clayton12fc3e02010-08-26 22:05:43 +00001055 return max_len;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001056}
1057
1058void
Enrico Granata223383e2011-08-16 23:24:13 +00001059CommandInterpreter::GetHelp (CommandReturnObject &result,
Enrico Granata08633ee2011-09-09 17:49:36 +00001060 uint32_t cmd_types)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001061{
1062 CommandObject::CommandMap::const_iterator pos;
Greg Claytonc7bece562013-01-25 18:06:21 +00001063 size_t max_len = FindLongestCommandWord (m_command_dict);
Enrico Granata223383e2011-08-16 23:24:13 +00001064
1065 if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001066 {
Enrico Granata223383e2011-08-16 23:24:13 +00001067
1068 result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
1069 result.AppendMessage("");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001070
Enrico Granata223383e2011-08-16 23:24:13 +00001071 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
1072 {
1073 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1074 max_len);
1075 }
1076 result.AppendMessage("");
1077
1078 }
1079
Greg Clayton5521f992011-10-28 21:38:01 +00001080 if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001081 {
Jim Ingham49e80a12010-10-22 18:47:16 +00001082 result.AppendMessage("The following is a list of your current command abbreviations "
Johnny Chenb89982d2011-04-21 00:39:18 +00001083 "(see 'help command alias' for more info):");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001084 result.AppendMessage("");
Greg Clayton12fc3e02010-08-26 22:05:43 +00001085 max_len = FindLongestCommandWord (m_alias_dict);
1086
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001087 for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
1088 {
1089 StreamString sstr;
1090 StreamString translation_and_help;
1091 std::string entry_name = pos->first;
1092 std::string second_entry = pos->second.get()->GetCommandName();
1093 GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
1094
1095 translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp());
1096 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
1097 translation_and_help.GetData(), max_len);
1098 }
1099 result.AppendMessage("");
1100 }
1101
Greg Clayton5521f992011-10-28 21:38:01 +00001102 if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001103 {
1104 result.AppendMessage ("The following is a list of your current user-defined commands:");
1105 result.AppendMessage("");
Enrico Granata223383e2011-08-16 23:24:13 +00001106 max_len = FindLongestCommandWord (m_user_dict);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001107 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
1108 {
Enrico Granata223383e2011-08-16 23:24:13 +00001109 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1110 max_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001111 }
1112 result.AppendMessage("");
1113 }
1114
1115 result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
1116}
1117
Caroline Tice844d2302010-12-09 22:52:49 +00001118CommandObject *
1119CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001120{
Caroline Tice844d2302010-12-09 22:52:49 +00001121 // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
1122 // eventually be invoked by the given command line.
1123
1124 CommandObject *cmd_obj = NULL;
1125 std::string white_space (" \t\v");
1126 size_t start = command_string.find_first_not_of (white_space);
1127 size_t end = 0;
1128 bool done = false;
1129 while (!done)
1130 {
1131 if (start != std::string::npos)
1132 {
1133 // Get the next word from command_string.
1134 end = command_string.find_first_of (white_space, start);
1135 if (end == std::string::npos)
1136 end = command_string.size();
1137 std::string cmd_word = command_string.substr (start, end - start);
1138
1139 if (cmd_obj == NULL)
1140 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
1141 // command or alias.
1142 cmd_obj = GetCommandObject (cmd_word.c_str());
1143 else if (cmd_obj->IsMultiwordObject ())
1144 {
1145 // 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 +00001146 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001147 if (sub_cmd_obj)
1148 cmd_obj = sub_cmd_obj;
1149 else // cmd_word was not a valid sub-command word, so we are donee
1150 done = true;
1151 }
1152 else
1153 // We have a cmd_obj and it is not a multi-word object, so we are done.
1154 done = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001155
Caroline Tice844d2302010-12-09 22:52:49 +00001156 // If we didn't find a valid command object, or our command object is not a multi-word object, or
1157 // we are at the end of the command_string, then we are done. Otherwise, find the start of the
1158 // next word.
1159
1160 if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
1161 done = true;
1162 else
1163 start = command_string.find_first_not_of (white_space, end);
1164 }
1165 else
1166 // Unable to find any more words.
1167 done = true;
1168 }
1169
1170 if (end == command_string.size())
1171 command_string.clear();
1172 else
1173 command_string = command_string.substr(end);
1174
1175 return cmd_obj;
1176}
1177
Greg Clayton51964162011-10-25 00:36:27 +00001178static const char *k_white_space = " \t\v";
Greg Clayton5521f992011-10-28 21:38:01 +00001179static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
Greg Clayton51964162011-10-25 00:36:27 +00001180static void
1181StripLeadingSpaces (std::string &s)
Caroline Tice844d2302010-12-09 22:52:49 +00001182{
Greg Clayton51964162011-10-25 00:36:27 +00001183 if (!s.empty())
Caroline Tice844d2302010-12-09 22:52:49 +00001184 {
Greg Clayton51964162011-10-25 00:36:27 +00001185 size_t pos = s.find_first_not_of (k_white_space);
1186 if (pos == std::string::npos)
1187 s.clear();
1188 else if (pos == 0)
1189 return;
1190 s.erase (0, pos);
1191 }
1192}
1193
Greg Clayton93c62e62011-11-09 23:25:03 +00001194static size_t
1195FindArgumentTerminator (const std::string &s)
1196{
Greg Clayton93c62e62011-11-09 23:25:03 +00001197 const size_t s_len = s.size();
1198 size_t offset = 0;
1199 while (offset < s_len)
1200 {
1201 size_t pos = s.find ("--", offset);
1202 if (pos == std::string::npos)
1203 break;
1204 if (pos > 0)
1205 {
1206 if (isspace(s[pos-1]))
1207 {
1208 // Check if the string ends "\s--" (where \s is a space character)
1209 // or if we have "\s--\s".
1210 if ((pos + 2 >= s_len) || isspace(s[pos+2]))
1211 {
Greg Clayton93c62e62011-11-09 23:25:03 +00001212 return pos;
1213 }
1214 }
1215 }
1216 offset = pos + 2;
1217 }
Greg Clayton93c62e62011-11-09 23:25:03 +00001218 return std::string::npos;
1219}
1220
Greg Clayton51964162011-10-25 00:36:27 +00001221static bool
Greg Clayton5521f992011-10-28 21:38:01 +00001222ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char &quote_char)
Greg Clayton51964162011-10-25 00:36:27 +00001223{
Greg Clayton5521f992011-10-28 21:38:01 +00001224 command.clear();
1225 suffix.clear();
Greg Clayton51964162011-10-25 00:36:27 +00001226 StripLeadingSpaces (command_string);
1227
1228 bool result = false;
1229 quote_char = '\0';
1230
1231 if (!command_string.empty())
1232 {
1233 const char first_char = command_string[0];
1234 if (first_char == '\'' || first_char == '"')
Caroline Tice844d2302010-12-09 22:52:49 +00001235 {
Greg Clayton51964162011-10-25 00:36:27 +00001236 quote_char = first_char;
1237 const size_t end_quote_pos = command_string.find (quote_char, 1);
1238 if (end_quote_pos == std::string::npos)
Caroline Tice2b5e8502011-05-11 16:07:06 +00001239 {
Greg Clayton5521f992011-10-28 21:38:01 +00001240 command.swap (command_string);
Greg Clayton51964162011-10-25 00:36:27 +00001241 command_string.erase ();
Caroline Tice2b5e8502011-05-11 16:07:06 +00001242 }
1243 else
1244 {
Greg Clayton5521f992011-10-28 21:38:01 +00001245 command.assign (command_string, 1, end_quote_pos - 1);
Greg Clayton51964162011-10-25 00:36:27 +00001246 if (end_quote_pos + 1 < command_string.size())
1247 command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
1248 else
1249 command_string.erase ();
Caroline Tice2b5e8502011-05-11 16:07:06 +00001250 }
Caroline Tice844d2302010-12-09 22:52:49 +00001251 }
1252 else
1253 {
Greg Clayton51964162011-10-25 00:36:27 +00001254 const size_t first_space_pos = command_string.find_first_of (k_white_space);
1255 if (first_space_pos == std::string::npos)
Caroline Tice2b5e8502011-05-11 16:07:06 +00001256 {
Greg Clayton5521f992011-10-28 21:38:01 +00001257 command.swap (command_string);
Greg Clayton51964162011-10-25 00:36:27 +00001258 command_string.erase();
Caroline Tice2b5e8502011-05-11 16:07:06 +00001259 }
1260 else
1261 {
Greg Clayton5521f992011-10-28 21:38:01 +00001262 command.assign (command_string, 0, first_space_pos);
1263 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
Caroline Tice2b5e8502011-05-11 16:07:06 +00001264 }
Caroline Tice844d2302010-12-09 22:52:49 +00001265 }
Greg Clayton51964162011-10-25 00:36:27 +00001266 result = true;
Caroline Tice844d2302010-12-09 22:52:49 +00001267 }
Greg Clayton5521f992011-10-28 21:38:01 +00001268
1269
1270 if (!command.empty())
1271 {
1272 // actual commands can't start with '-' or '_'
1273 if (command[0] != '-' && command[0] != '_')
1274 {
1275 size_t pos = command.find_first_not_of(k_valid_command_chars);
1276 if (pos > 0 && pos != std::string::npos)
1277 {
1278 suffix.assign (command.begin() + pos, command.end());
1279 command.erase (pos);
1280 }
1281 }
1282 }
Greg Clayton51964162011-10-25 00:36:27 +00001283
1284 return result;
Caroline Tice844d2302010-12-09 22:52:49 +00001285}
1286
Greg Clayton5521f992011-10-28 21:38:01 +00001287CommandObject *
1288CommandInterpreter::BuildAliasResult (const char *alias_name,
1289 std::string &raw_input_string,
1290 std::string &alias_result,
1291 CommandReturnObject &result)
Caroline Tice844d2302010-12-09 22:52:49 +00001292{
Greg Clayton5521f992011-10-28 21:38:01 +00001293 CommandObject *alias_cmd_obj = NULL;
Caroline Tice844d2302010-12-09 22:52:49 +00001294 Args cmd_args (raw_input_string.c_str());
1295 alias_cmd_obj = GetCommandObject (alias_name);
1296 StreamString result_str;
1297
1298 if (alias_cmd_obj)
1299 {
1300 std::string alias_name_str = alias_name;
1301 if ((cmd_args.GetArgumentCount() == 0)
1302 || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
1303 cmd_args.Unshift (alias_name);
1304
1305 result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
1306 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1307
1308 if (option_arg_vector_sp.get())
1309 {
1310 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1311
1312 for (int i = 0; i < option_arg_vector->size(); ++i)
1313 {
1314 OptionArgPair option_pair = (*option_arg_vector)[i];
1315 OptionArgValue value_pair = option_pair.second;
1316 int value_type = value_pair.first;
1317 std::string option = option_pair.first;
1318 std::string value = value_pair.second;
1319 if (option.compare ("<argument>") == 0)
1320 result_str.Printf (" %s", value.c_str());
1321 else
1322 {
1323 result_str.Printf (" %s", option.c_str());
1324 if (value_type != optional_argument)
1325 result_str.Printf (" ");
1326 if (value.compare ("<no_argument>") != 0)
1327 {
1328 int index = GetOptionArgumentPosition (value.c_str());
1329 if (index == 0)
1330 result_str.Printf ("%s", value.c_str());
1331 else if (index >= cmd_args.GetArgumentCount())
1332 {
1333
1334 result.AppendErrorWithFormat
1335 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
1336 index);
1337 result.SetStatus (eReturnStatusFailed);
Greg Clayton5521f992011-10-28 21:38:01 +00001338 return alias_cmd_obj;
Caroline Tice844d2302010-12-09 22:52:49 +00001339 }
1340 else
1341 {
1342 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
1343 if (strpos != std::string::npos)
1344 raw_input_string = raw_input_string.erase (strpos,
1345 strlen (cmd_args.GetArgumentAtIndex (index)));
1346 result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
1347 }
1348 }
1349 }
1350 }
1351 }
1352
1353 alias_result = result_str.GetData();
1354 }
Greg Clayton5521f992011-10-28 21:38:01 +00001355 return alias_cmd_obj;
Caroline Tice844d2302010-12-09 22:52:49 +00001356}
1357
Greg Clayton5a314712011-10-14 07:41:33 +00001358Error
1359CommandInterpreter::PreprocessCommand (std::string &command)
1360{
1361 // The command preprocessor needs to do things to the command
1362 // line before any parsing of arguments or anything else is done.
1363 // The only current stuff that gets proprocessed is anyting enclosed
1364 // in backtick ('`') characters is evaluated as an expression and
1365 // the result of the expression must be a scalar that can be substituted
1366 // into the command. An example would be:
1367 // (lldb) memory read `$rsp + 20`
1368 Error error; // Error for any expressions that might not evaluate
1369 size_t start_backtick;
1370 size_t pos = 0;
1371 while ((start_backtick = command.find ('`', pos)) != std::string::npos)
1372 {
1373 if (start_backtick > 0 && command[start_backtick-1] == '\\')
1374 {
1375 // The backtick was preceeded by a '\' character, remove the slash
1376 // and don't treat the backtick as the start of an expression
1377 command.erase(start_backtick-1, 1);
1378 // No need to add one to start_backtick since we just deleted a char
1379 pos = start_backtick;
1380 }
1381 else
1382 {
1383 const size_t expr_content_start = start_backtick + 1;
1384 const size_t end_backtick = command.find ('`', expr_content_start);
1385 if (end_backtick == std::string::npos)
1386 return error;
1387 else if (end_backtick == expr_content_start)
1388 {
1389 // Empty expression (two backticks in a row)
1390 command.erase (start_backtick, 2);
1391 }
1392 else
1393 {
1394 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
1395
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00001396 ExecutionContext exe_ctx(GetExecutionContext());
1397 Target *target = exe_ctx.GetTargetPtr();
Johnny Chen51ea0ad2011-10-29 00:21:50 +00001398 // Get a dummy target to allow for calculator mode while processing backticks.
1399 // This also helps break the infinite loop caused when target is null.
1400 if (!target)
1401 target = Host::GetDummyTarget(GetDebugger()).get();
Greg Clayton5a314712011-10-14 07:41:33 +00001402 if (target)
1403 {
Greg Clayton5a314712011-10-14 07:41:33 +00001404 ValueObjectSP expr_result_valobj_sp;
Enrico Granatad4439aa2012-09-05 20:41:26 +00001405
Jim Ingham35e1bda2012-10-16 21:41:58 +00001406 EvaluateExpressionOptions options;
Enrico Granatad4439aa2012-09-05 20:41:26 +00001407 options.SetCoerceToId(false)
1408 .SetUnwindOnError(true)
Jim Ingham184e9812013-01-15 02:47:48 +00001409 .SetIgnoreBreakpoints(true)
Enrico Granatad4439aa2012-09-05 20:41:26 +00001410 .SetKeepInMemory(false)
Jim Ingham35e1bda2012-10-16 21:41:58 +00001411 .SetRunOthers(true)
1412 .SetTimeoutUsec(0);
Enrico Granatad4439aa2012-09-05 20:41:26 +00001413
Greg Clayton5a314712011-10-14 07:41:33 +00001414 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
Enrico Granatad4439aa2012-09-05 20:41:26 +00001415 exe_ctx.GetFramePtr(),
Enrico Granata3372f582012-07-16 23:10:35 +00001416 expr_result_valobj_sp,
Enrico Granatad4439aa2012-09-05 20:41:26 +00001417 options);
1418
Greg Clayton5a314712011-10-14 07:41:33 +00001419 if (expr_result == eExecutionCompleted)
1420 {
1421 Scalar scalar;
1422 if (expr_result_valobj_sp->ResolveValue (scalar))
1423 {
1424 command.erase (start_backtick, end_backtick - start_backtick + 1);
1425 StreamString value_strm;
1426 const bool show_type = false;
1427 scalar.GetValue (&value_strm, show_type);
1428 size_t value_string_size = value_strm.GetSize();
1429 if (value_string_size)
1430 {
1431 command.insert (start_backtick, value_strm.GetData(), value_string_size);
1432 pos = start_backtick + value_string_size;
1433 continue;
1434 }
1435 else
1436 {
1437 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1438 }
1439 }
1440 else
1441 {
1442 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1443 }
1444 }
1445 else
1446 {
1447 if (expr_result_valobj_sp)
1448 error = expr_result_valobj_sp->GetError();
1449 if (error.Success())
1450 {
1451
1452 switch (expr_result)
1453 {
1454 case eExecutionSetupError:
1455 error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
1456 break;
1457 case eExecutionCompleted:
1458 break;
1459 case eExecutionDiscarded:
1460 error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
1461 break;
1462 case eExecutionInterrupted:
1463 error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
1464 break;
Jim Ingham184e9812013-01-15 02:47:48 +00001465 case eExecutionHitBreakpoint:
1466 error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
1467 break;
Greg Clayton5a314712011-10-14 07:41:33 +00001468 case eExecutionTimedOut:
1469 error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
1470 break;
1471 }
1472 }
1473 }
1474 }
1475 }
1476 if (error.Fail())
1477 break;
1478 }
1479 }
1480 return error;
1481}
1482
1483
Caroline Tice844d2302010-12-09 22:52:49 +00001484bool
1485CommandInterpreter::HandleCommand (const char *command_line,
Enrico Granata5f5ab602012-05-31 01:09:06 +00001486 LazyBool lazy_add_to_history,
Caroline Tice844d2302010-12-09 22:52:49 +00001487 CommandReturnObject &result,
Jim Inghame16c50a2011-02-18 00:54:25 +00001488 ExecutionContext *override_context,
Johnny Chen80fdd7c2011-10-05 00:42:59 +00001489 bool repeat_on_empty_command,
1490 bool no_context_switching)
Jim Inghame16c50a2011-02-18 00:54:25 +00001491
Caroline Tice844d2302010-12-09 22:52:49 +00001492{
Jim Inghame16c50a2011-02-18 00:54:25 +00001493
Caroline Tice844d2302010-12-09 22:52:49 +00001494 bool done = false;
1495 CommandObject *cmd_obj = NULL;
Caroline Tice844d2302010-12-09 22:52:49 +00001496 bool wants_raw_input = false;
1497 std::string command_string (command_line);
Jim Inghama5a97eb2011-07-12 03:12:18 +00001498 std::string original_command_string (command_line);
Caroline Tice844d2302010-12-09 22:52:49 +00001499
Greg Clayton5160ce52013-03-27 23:08:40 +00001500 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
Greg Clayton2d95dc9b2010-11-10 04:57:04 +00001501 Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
1502
1503 // Make a scoped cleanup object that will clear the crash description string
1504 // on exit of this function.
Enrico Granataf9fa6ee2011-07-12 00:18:11 +00001505 lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription);
Greg Clayton2d95dc9b2010-11-10 04:57:04 +00001506
Caroline Tice844d2302010-12-09 22:52:49 +00001507 if (log)
1508 log->Printf ("Processing command: %s", command_line);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001509
Jim Ingham30244832010-11-04 23:08:45 +00001510 Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
1511
Johnny Chen80fdd7c2011-10-05 00:42:59 +00001512 if (!no_context_switching)
1513 UpdateExecutionContext (override_context);
Enrico Granata5f5ab602012-05-31 01:09:06 +00001514
Enrico Granata5f5ab602012-05-31 01:09:06 +00001515 bool add_to_history;
1516 if (lazy_add_to_history == eLazyBoolCalculate)
1517 add_to_history = (m_command_source_depth == 0);
1518 else
1519 add_to_history = (lazy_add_to_history == eLazyBoolYes);
1520
Jim Inghame16c50a2011-02-18 00:54:25 +00001521 bool empty_command = false;
1522 bool comment_command = false;
1523 if (command_string.empty())
1524 empty_command = true;
1525 else
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001526 {
Jim Inghame16c50a2011-02-18 00:54:25 +00001527 const char *k_space_characters = "\t\n\v\f\r ";
1528
1529 size_t non_space = command_string.find_first_not_of (k_space_characters);
1530 // Check for empty line or comment line (lines whose first
1531 // non-space character is the comment character for this interpreter)
1532 if (non_space == std::string::npos)
1533 empty_command = true;
1534 else if (command_string[non_space] == m_comment_char)
1535 comment_command = true;
Enrico Granata7594f142013-06-17 22:51:50 +00001536 else if (command_string[non_space] == CommandHistory::g_repeat_char)
Jim Inghama5a97eb2011-07-12 03:12:18 +00001537 {
Enrico Granata7594f142013-06-17 22:51:50 +00001538 const char *history_string = m_command_history.FindString(command_string.c_str() + non_space);
Jim Inghama5a97eb2011-07-12 03:12:18 +00001539 if (history_string == NULL)
1540 {
1541 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
1542 result.SetStatus(eReturnStatusFailed);
1543 return false;
1544 }
1545 add_to_history = false;
1546 command_string = history_string;
1547 original_command_string = history_string;
1548 }
Jim Inghame16c50a2011-02-18 00:54:25 +00001549 }
1550
1551 if (empty_command)
1552 {
1553 if (repeat_on_empty_command)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001554 {
Enrico Granata7594f142013-06-17 22:51:50 +00001555 if (m_command_history.IsEmpty())
Jim Inghame16c50a2011-02-18 00:54:25 +00001556 {
1557 result.AppendError ("empty command");
1558 result.SetStatus(eReturnStatusFailed);
1559 return false;
1560 }
1561 else
1562 {
1563 command_line = m_repeat_command.c_str();
1564 command_string = command_line;
Jim Inghama5a97eb2011-07-12 03:12:18 +00001565 original_command_string = command_line;
Jim Inghame16c50a2011-02-18 00:54:25 +00001566 if (m_repeat_command.empty())
1567 {
1568 result.AppendErrorWithFormat("No auto repeat.\n");
1569 result.SetStatus (eReturnStatusFailed);
1570 return false;
1571 }
1572 }
1573 add_to_history = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001574 }
1575 else
1576 {
Jim Inghame16c50a2011-02-18 00:54:25 +00001577 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1578 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001579 }
Jim Inghame16c50a2011-02-18 00:54:25 +00001580 }
1581 else if (comment_command)
1582 {
1583 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1584 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001585 }
Caroline Tice2b5e8502011-05-11 16:07:06 +00001586
Greg Clayton5a314712011-10-14 07:41:33 +00001587
1588 Error error (PreprocessCommand (command_string));
1589
1590 if (error.Fail())
1591 {
1592 result.AppendError (error.AsCString());
1593 result.SetStatus(eReturnStatusFailed);
1594 return false;
1595 }
Caroline Tice844d2302010-12-09 22:52:49 +00001596 // Phase 1.
1597
1598 // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
1599 // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that
1600 // the user could have specified an alias, and in translating the alias there may also be command options and/or
1601 // even data (including raw text strings) that need to be found and inserted into the command line as part of
1602 // 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 +00001603 // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
Caroline Tice844d2302010-12-09 22:52:49 +00001604 // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
Caroline Ticed9d63362010-12-07 19:58:26 +00001605
Caroline Tice844d2302010-12-09 22:52:49 +00001606 StreamString revised_command_line;
Caroline Tice01274c02010-12-11 08:16:56 +00001607 size_t actual_cmd_name_len = 0;
Greg Clayton5521f992011-10-28 21:38:01 +00001608 std::string next_word;
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001609 StringList matches;
Caroline Tice844d2302010-12-09 22:52:49 +00001610 while (!done)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001611 {
Caroline Tice2b5e8502011-05-11 16:07:06 +00001612 char quote_char = '\0';
Greg Clayton5521f992011-10-28 21:38:01 +00001613 std::string suffix;
1614 ExtractCommand (command_string, next_word, suffix, quote_char);
1615 if (cmd_obj == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001616 {
Jim Ingham298f3782013-04-03 00:25:49 +00001617 std::string full_name;
1618 if (GetAliasFullName(next_word.c_str(), full_name))
Caroline Tice472362e2010-12-14 18:51:39 +00001619 {
Greg Clayton5521f992011-10-28 21:38:01 +00001620 std::string alias_result;
Jim Ingham298f3782013-04-03 00:25:49 +00001621 cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result);
Greg Clayton5521f992011-10-28 21:38:01 +00001622 revised_command_line.Printf ("%s", alias_result.c_str());
1623 if (cmd_obj)
1624 {
1625 wants_raw_input = cmd_obj->WantsRawCommandString ();
1626 actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
1627 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001628 }
1629 else
1630 {
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001631 cmd_obj = GetCommandObject (next_word.c_str(), &matches);
Greg Clayton5521f992011-10-28 21:38:01 +00001632 if (cmd_obj)
1633 {
1634 actual_cmd_name_len += next_word.length();
1635 revised_command_line.Printf ("%s", next_word.c_str());
1636 wants_raw_input = cmd_obj->WantsRawCommandString ();
1637 }
Caroline Tice2b5e8502011-05-11 16:07:06 +00001638 else
Greg Clayton5521f992011-10-28 21:38:01 +00001639 {
1640 revised_command_line.Printf ("%s", next_word.c_str());
1641 }
Caroline Tice844d2302010-12-09 22:52:49 +00001642 }
1643 }
1644 else
1645 {
Greg Clayton5521f992011-10-28 21:38:01 +00001646 if (cmd_obj->IsMultiwordObject ())
1647 {
Greg Clayton998255b2012-10-13 02:07:45 +00001648 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str());
Greg Clayton5521f992011-10-28 21:38:01 +00001649 if (sub_cmd_obj)
1650 {
1651 actual_cmd_name_len += next_word.length() + 1;
1652 revised_command_line.Printf (" %s", next_word.c_str());
1653 cmd_obj = sub_cmd_obj;
1654 wants_raw_input = cmd_obj->WantsRawCommandString ();
1655 }
1656 else
1657 {
1658 if (quote_char)
1659 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1660 else
1661 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1662 done = true;
1663 }
1664 }
Caroline Tice2b5e8502011-05-11 16:07:06 +00001665 else
Greg Clayton5521f992011-10-28 21:38:01 +00001666 {
1667 if (quote_char)
1668 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1669 else
1670 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1671 done = true;
1672 }
Caroline Tice844d2302010-12-09 22:52:49 +00001673 }
1674
1675 if (cmd_obj == NULL)
1676 {
Greg Claytonc7bece562013-01-25 18:06:21 +00001677 const size_t num_matches = matches.GetSize();
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001678 if (matches.GetSize() > 1) {
Greg Claytonc7bece562013-01-25 18:06:21 +00001679 StreamString error_msg;
1680 error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001681
1682 for (uint32_t i = 0; i < num_matches; ++i) {
Greg Claytonc7bece562013-01-25 18:06:21 +00001683 error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i));
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001684 }
Greg Claytonc7bece562013-01-25 18:06:21 +00001685 result.AppendRawError (error_msg.GetString().c_str());
Filipe Cabecinhasaf1537f2012-05-16 23:25:54 +00001686 } else {
1687 // We didn't have only one match, otherwise we wouldn't get here.
1688 assert(num_matches == 0);
1689 result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
1690 }
Caroline Tice844d2302010-12-09 22:52:49 +00001691 result.SetStatus (eReturnStatusFailed);
1692 return false;
1693 }
1694
Greg Clayton5521f992011-10-28 21:38:01 +00001695 if (cmd_obj->IsMultiwordObject ())
1696 {
1697 if (!suffix.empty())
1698 {
1699
Enrico Granataaded51d2013-06-12 00:44:43 +00001700 result.AppendErrorWithFormat ("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n",
1701 cmd_obj->GetCommandName(),
1702 next_word.empty() ? "" : next_word.c_str(),
1703 next_word.empty() ? " -- " : " ",
Greg Clayton5521f992011-10-28 21:38:01 +00001704 suffix.c_str());
1705 result.SetStatus (eReturnStatusFailed);
1706 return false;
1707 }
1708 }
1709 else
1710 {
1711 // If we found a normal command, we are done
1712 done = true;
1713 if (!suffix.empty())
1714 {
1715 switch (suffix[0])
1716 {
1717 case '/':
1718 // GDB format suffixes
Greg Clayton52ec56c2011-10-29 00:57:28 +00001719 {
1720 Options *command_options = cmd_obj->GetOptions();
1721 if (command_options && command_options->SupportsLongOption("gdb-format"))
1722 {
Greg Clayton93c62e62011-11-09 23:25:03 +00001723 std::string gdb_format_option ("--gdb-format=");
1724 gdb_format_option += (suffix.c_str() + 1);
1725
1726 bool inserted = false;
1727 std::string &cmd = revised_command_line.GetString();
1728 size_t arg_terminator_idx = FindArgumentTerminator (cmd);
1729 if (arg_terminator_idx != std::string::npos)
1730 {
1731 // Insert the gdb format option before the "--" that terminates options
1732 gdb_format_option.append(1,' ');
1733 cmd.insert(arg_terminator_idx, gdb_format_option);
1734 inserted = true;
1735 }
1736
1737 if (!inserted)
1738 revised_command_line.Printf (" %s", gdb_format_option.c_str());
1739
1740 if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
1741 revised_command_line.PutCString (" --");
Greg Clayton52ec56c2011-10-29 00:57:28 +00001742 }
1743 else
1744 {
1745 result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n",
1746 cmd_obj->GetCommandName());
1747 result.SetStatus (eReturnStatusFailed);
1748 return false;
1749 }
1750 }
Greg Clayton5521f992011-10-28 21:38:01 +00001751 break;
Johnny Chen8e9383d2011-10-31 22:22:06 +00001752
1753 default:
1754 result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n",
1755 suffix.c_str());
1756 result.SetStatus (eReturnStatusFailed);
1757 return false;
1758
Greg Clayton5521f992011-10-28 21:38:01 +00001759 }
1760 }
1761 }
Caroline Tice844d2302010-12-09 22:52:49 +00001762 if (command_string.length() == 0)
1763 done = true;
1764
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001765 }
Caroline Tice844d2302010-12-09 22:52:49 +00001766
Greg Clayton5521f992011-10-28 21:38:01 +00001767 if (!command_string.empty())
Caroline Tice844d2302010-12-09 22:52:49 +00001768 revised_command_line.Printf (" %s", command_string.c_str());
1769
1770 // End of Phase 1.
1771 // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
1772 // specified was valid; revised_command_line contains the complete command line (including command name(s)),
1773 // fully translated with all substitutions & translations taken care of (still in raw text format); and
1774 // wants_raw_input specifies whether the Execute method expects raw input or not.
1775
1776
1777 if (log)
1778 {
1779 log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
1780 log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
1781 log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
1782 }
1783
1784 // Phase 2.
1785 // Take care of things like setting up the history command & calling the appropriate Execute method on the
1786 // CommandObject, with the appropriate arguments.
1787
1788 if (cmd_obj != NULL)
1789 {
1790 if (add_to_history)
1791 {
1792 Args command_args (revised_command_line.GetData());
1793 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
1794 if (repeat_command != NULL)
1795 m_repeat_command.assign(repeat_command);
1796 else
Jim Inghama5a97eb2011-07-12 03:12:18 +00001797 m_repeat_command.assign(original_command_string.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001798
Enrico Granata7594f142013-06-17 22:51:50 +00001799 m_command_history.AppendString (original_command_string);
Caroline Tice844d2302010-12-09 22:52:49 +00001800 }
1801
1802 command_string = revised_command_line.GetData();
1803 std::string command_name (cmd_obj->GetCommandName());
Caroline Tice01274c02010-12-11 08:16:56 +00001804 std::string remainder;
1805 if (actual_cmd_name_len < command_string.length())
1806 remainder = command_string.substr (actual_cmd_name_len); // Note: 'actual_cmd_name_len' may be considerably shorter
1807 // than cmd_obj->GetCommandName(), because name completion
1808 // allows users to enter short versions of the names,
1809 // e.g. 'br s' for 'breakpoint set'.
Caroline Tice844d2302010-12-09 22:52:49 +00001810
1811 // Remove any initial spaces
1812 std::string white_space (" \t\v");
1813 size_t pos = remainder.find_first_not_of (white_space);
1814 if (pos != 0 && pos != std::string::npos)
Greg Claytona3482592011-04-22 20:58:45 +00001815 remainder.erase(0, pos);
Caroline Tice844d2302010-12-09 22:52:49 +00001816
1817 if (log)
Jason Molendabfb36ff2011-08-25 00:20:04 +00001818 log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001819
Jim Ingham5a988412012-06-08 21:56:10 +00001820 cmd_obj->Execute (remainder.c_str(), result);
Caroline Tice844d2302010-12-09 22:52:49 +00001821 }
1822 else
1823 {
1824 // We didn't find the first command object, so complete the first argument.
1825 Args command_args (revised_command_line.GetData());
1826 StringList matches;
1827 int num_matches;
1828 int cursor_index = 0;
1829 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
1830 bool word_complete;
1831 num_matches = HandleCompletionMatches (command_args,
1832 cursor_index,
1833 cursor_char_position,
1834 0,
1835 -1,
1836 word_complete,
1837 matches);
1838
1839 if (num_matches > 0)
1840 {
1841 std::string error_msg;
1842 error_msg.assign ("ambiguous command '");
1843 error_msg.append(command_args.GetArgumentAtIndex(0));
1844 error_msg.append ("'.");
1845
1846 error_msg.append (" Possible completions:");
1847 for (int i = 0; i < num_matches; i++)
1848 {
1849 error_msg.append ("\n\t");
1850 error_msg.append (matches.GetStringAtIndex (i));
1851 }
1852 error_msg.append ("\n");
Greg Claytonc7bece562013-01-25 18:06:21 +00001853 result.AppendRawError (error_msg.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +00001854 }
1855 else
1856 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
1857
1858 result.SetStatus (eReturnStatusFailed);
1859 }
1860
Jason Molendabfb36ff2011-08-25 00:20:04 +00001861 if (log)
1862 log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
1863
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001864 return result.Succeeded();
1865}
1866
1867int
1868CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
1869 int &cursor_index,
1870 int &cursor_char_position,
1871 int match_start_point,
1872 int max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +00001873 bool &word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001874 StringList &matches)
1875{
1876 int num_command_matches = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001877 bool look_for_subcommand = false;
Jim Ingham558ce122010-06-30 05:02:46 +00001878
1879 // For any of the command completions a unique match will be a complete word.
1880 word_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001881
1882 if (cursor_index == -1)
1883 {
1884 // We got nothing on the command line, so return the list of commands
Jim Ingham279a6c22010-07-06 22:46:59 +00001885 bool include_aliases = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001886 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
1887 }
1888 else if (cursor_index == 0)
1889 {
1890 // The cursor is in the first argument, so just do a lookup in the dictionary.
Jim Ingham279a6c22010-07-06 22:46:59 +00001891 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001892 num_command_matches = matches.GetSize();
1893
1894 if (num_command_matches == 1
1895 && cmd_obj && cmd_obj->IsMultiwordObject()
1896 && matches.GetStringAtIndex(0) != NULL
1897 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
1898 {
1899 look_for_subcommand = true;
1900 num_command_matches = 0;
1901 matches.DeleteStringAtIndex(0);
1902 parsed_line.AppendArgument ("");
1903 cursor_index++;
1904 cursor_char_position = 0;
1905 }
1906 }
1907
1908 if (cursor_index > 0 || look_for_subcommand)
1909 {
1910 // We are completing further on into a commands arguments, so find the command and tell it
1911 // to complete the command.
1912 // First see if there is a matching initial command:
Jim Ingham279a6c22010-07-06 22:46:59 +00001913 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001914 if (command_object == NULL)
1915 {
1916 return 0;
1917 }
1918 else
1919 {
1920 parsed_line.Shift();
1921 cursor_index--;
Greg Claytona7015092010-09-18 01:14:36 +00001922 num_command_matches = command_object->HandleCompletion (parsed_line,
Greg Clayton66111032010-06-23 01:19:29 +00001923 cursor_index,
1924 cursor_char_position,
1925 match_start_point,
Jim Ingham558ce122010-06-30 05:02:46 +00001926 max_return_elements,
1927 word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001928 matches);
1929 }
1930 }
1931
1932 return num_command_matches;
1933
1934}
1935
1936int
1937CommandInterpreter::HandleCompletion (const char *current_line,
1938 const char *cursor,
1939 const char *last_char,
1940 int match_start_point,
1941 int max_return_elements,
1942 StringList &matches)
1943{
1944 // We parse the argument up to the cursor, so the last argument in parsed_line is
1945 // the one containing the cursor, and the cursor is after the last character.
1946
1947 Args parsed_line(current_line, last_char - current_line);
1948 Args partial_parsed_line(current_line, cursor - current_line);
1949
Jim Inghama5a97eb2011-07-12 03:12:18 +00001950 // Don't complete comments, and if the line we are completing is just the history repeat character,
1951 // substitute the appropriate history line.
1952 const char *first_arg = parsed_line.GetArgumentAtIndex(0);
1953 if (first_arg)
1954 {
1955 if (first_arg[0] == m_comment_char)
1956 return 0;
Enrico Granata7594f142013-06-17 22:51:50 +00001957 else if (first_arg[0] == CommandHistory::g_repeat_char)
Jim Inghama5a97eb2011-07-12 03:12:18 +00001958 {
Enrico Granata7594f142013-06-17 22:51:50 +00001959 const char *history_string = m_command_history.FindString (first_arg);
Jim Inghama5a97eb2011-07-12 03:12:18 +00001960 if (history_string != NULL)
1961 {
1962 matches.Clear();
1963 matches.InsertStringAtIndex(0, history_string);
1964 return -2;
1965 }
1966 else
1967 return 0;
1968
1969 }
1970 }
1971
1972
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001973 int num_args = partial_parsed_line.GetArgumentCount();
1974 int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
1975 int cursor_char_position;
1976
1977 if (cursor_index == -1)
1978 cursor_char_position = 0;
1979 else
1980 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
Jim Inghamfe0c4252010-12-14 19:56:01 +00001981
1982 if (cursor > current_line && cursor[-1] == ' ')
1983 {
1984 // We are just after a space. If we are in an argument, then we will continue
1985 // parsing, but if we are between arguments, then we have to complete whatever the next
1986 // element would be.
1987 // We can distinguish the two cases because if we are in an argument (e.g. because the space is
1988 // protected by a quote) then the space will also be in the parsed argument...
1989
1990 const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
1991 if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
1992 {
1993 parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '"');
1994 cursor_index++;
1995 cursor_char_position = 0;
1996 }
1997 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001998
1999 int num_command_matches;
2000
2001 matches.Clear();
2002
2003 // Only max_return_elements == -1 is supported at present:
2004 assert (max_return_elements == -1);
Jim Ingham558ce122010-06-30 05:02:46 +00002005 bool word_complete;
Greg Clayton66111032010-06-23 01:19:29 +00002006 num_command_matches = HandleCompletionMatches (parsed_line,
2007 cursor_index,
2008 cursor_char_position,
2009 match_start_point,
Jim Ingham558ce122010-06-30 05:02:46 +00002010 max_return_elements,
2011 word_complete,
Greg Clayton66111032010-06-23 01:19:29 +00002012 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002013
2014 if (num_command_matches <= 0)
2015 return num_command_matches;
2016
2017 if (num_args == 0)
2018 {
2019 // If we got an empty string, insert nothing.
2020 matches.InsertStringAtIndex(0, "");
2021 }
2022 else
2023 {
2024 // Now figure out if there is a common substring, and if so put that in element 0, otherwise
2025 // put an empty string in element 0.
2026 std::string command_partial_str;
2027 if (cursor_index >= 0)
Jim Ingham49e80a12010-10-22 18:47:16 +00002028 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
2029 parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002030
2031 std::string common_prefix;
2032 matches.LongestCommonPrefix (common_prefix);
Greg Claytonc7bece562013-01-25 18:06:21 +00002033 const size_t partial_name_len = command_partial_str.size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002034
2035 // If we matched a unique single command, add a space...
Jim Ingham558ce122010-06-30 05:02:46 +00002036 // Only do this if the completer told us this was a complete word, however...
2037 if (num_command_matches == 1 && word_complete)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002038 {
2039 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
2040 if (quote_char != '\0')
2041 common_prefix.push_back(quote_char);
2042
2043 common_prefix.push_back(' ');
2044 }
2045 common_prefix.erase (0, partial_name_len);
2046 matches.InsertStringAtIndex(0, common_prefix.c_str());
2047 }
2048 return num_command_matches;
2049}
2050
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002051
2052CommandInterpreter::~CommandInterpreter ()
2053{
2054}
2055
2056const char *
2057CommandInterpreter::GetPrompt ()
2058{
Caroline Ticedaccaa92010-09-20 20:44:43 +00002059 return m_debugger.GetPrompt();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002060}
2061
2062void
2063CommandInterpreter::SetPrompt (const char *new_prompt)
2064{
Caroline Ticedaccaa92010-09-20 20:44:43 +00002065 m_debugger.SetPrompt (new_prompt);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002066}
2067
Jim Ingham97a6dc72010-10-04 19:49:29 +00002068size_t
Greg Clayton51b1e2d2011-02-09 01:08:52 +00002069CommandInterpreter::GetConfirmationInputReaderCallback
2070(
2071 void *baton,
2072 InputReader &reader,
2073 lldb::InputReaderAction action,
2074 const char *bytes,
2075 size_t bytes_len
2076)
Jim Ingham97a6dc72010-10-04 19:49:29 +00002077{
Greg Clayton51b1e2d2011-02-09 01:08:52 +00002078 File &out_file = reader.GetDebugger().GetOutputFile();
Jim Ingham97a6dc72010-10-04 19:49:29 +00002079 bool *response_ptr = (bool *) baton;
2080
2081 switch (action)
2082 {
2083 case eInputReaderActivate:
Greg Clayton51b1e2d2011-02-09 01:08:52 +00002084 if (out_file.IsValid())
Jim Ingham97a6dc72010-10-04 19:49:29 +00002085 {
2086 if (reader.GetPrompt())
Caroline Tice31f7d462011-02-02 01:17:56 +00002087 {
Greg Clayton51b1e2d2011-02-09 01:08:52 +00002088 out_file.Printf ("%s", reader.GetPrompt());
2089 out_file.Flush ();
Caroline Tice31f7d462011-02-02 01:17:56 +00002090 }
Jim Ingham97a6dc72010-10-04 19:49:29 +00002091 }
2092 break;
2093
2094 case eInputReaderDeactivate:
2095 break;
2096
2097 case eInputReaderReactivate:
Greg Clayton51b1e2d2011-02-09 01:08:52 +00002098 if (out_file.IsValid() && reader.GetPrompt())
Caroline Tice31f7d462011-02-02 01:17:56 +00002099 {
Greg Clayton51b1e2d2011-02-09 01:08:52 +00002100 out_file.Printf ("%s", reader.GetPrompt());
2101 out_file.Flush ();
Caroline Tice31f7d462011-02-02 01:17:56 +00002102 }
Jim Ingham97a6dc72010-10-04 19:49:29 +00002103 break;
Caroline Tice969ed3d2011-05-02 20:41:46 +00002104
2105 case eInputReaderAsynchronousOutputWritten:
2106 break;
2107
Jim Ingham97a6dc72010-10-04 19:49:29 +00002108 case eInputReaderGotToken:
2109 if (bytes_len == 0)
2110 {
2111 reader.SetIsDone(true);
2112 }
Jim Inghamc8b47582011-11-14 20:02:01 +00002113 else if (bytes[0] == 'y' || bytes[0] == 'Y')
Jim Ingham97a6dc72010-10-04 19:49:29 +00002114 {
2115 *response_ptr = true;
2116 reader.SetIsDone(true);
2117 }
Jim Inghamc8b47582011-11-14 20:02:01 +00002118 else if (bytes[0] == 'n' || bytes[0] == 'N')
Jim Ingham97a6dc72010-10-04 19:49:29 +00002119 {
2120 *response_ptr = false;
2121 reader.SetIsDone(true);
2122 }
2123 else
2124 {
Greg Clayton51b1e2d2011-02-09 01:08:52 +00002125 if (out_file.IsValid() && !reader.IsDone() && reader.GetPrompt())
Jim Ingham97a6dc72010-10-04 19:49:29 +00002126 {
Jim Ingham78d61482011-11-17 01:22:00 +00002127 out_file.Printf ("Please answer \"y\" or \"n\".\n%s", reader.GetPrompt());
Greg Clayton51b1e2d2011-02-09 01:08:52 +00002128 out_file.Flush ();
Jim Ingham97a6dc72010-10-04 19:49:29 +00002129 }
2130 }
2131 break;
2132
Caroline Ticeefed6132010-11-19 20:47:54 +00002133 case eInputReaderInterrupt:
2134 case eInputReaderEndOfFile:
2135 *response_ptr = false; // Assume ^C or ^D means cancel the proposed action
2136 reader.SetIsDone (true);
2137 break;
2138
Jim Ingham97a6dc72010-10-04 19:49:29 +00002139 case eInputReaderDone:
2140 break;
2141 }
2142
2143 return bytes_len;
2144
2145}
2146
2147bool
2148CommandInterpreter::Confirm (const char *message, bool default_answer)
2149{
Jim Ingham3bcdb292010-10-04 22:44:14 +00002150 // Check AutoConfirm first:
2151 if (m_debugger.GetAutoConfirm())
2152 return default_answer;
2153
Jim Ingham97a6dc72010-10-04 19:49:29 +00002154 InputReaderSP reader_sp (new InputReader(GetDebugger()));
2155 bool response = default_answer;
2156 if (reader_sp)
2157 {
2158 std::string prompt(message);
2159 prompt.append(": [");
2160 if (default_answer)
2161 prompt.append ("Y/n] ");
2162 else
2163 prompt.append ("y/N] ");
2164
2165 Error err (reader_sp->Initialize (CommandInterpreter::GetConfirmationInputReaderCallback,
2166 &response, // baton
2167 eInputReaderGranularityLine, // token size, to pass to callback function
2168 NULL, // end token
2169 prompt.c_str(), // prompt
2170 true)); // echo input
2171 if (err.Success())
2172 {
2173 GetDebugger().PushInputReader (reader_sp);
2174 }
2175 reader_sp->WaitOnReaderIsDone();
2176 }
2177 return response;
2178}
2179
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002180OptionArgVectorSP
2181CommandInterpreter::GetAliasOptions (const char *alias_name)
2182{
2183 OptionArgMap::iterator pos;
2184 OptionArgVectorSP ret_val;
2185
2186 std::string alias (alias_name);
2187
2188 if (HasAliasOptions())
2189 {
2190 pos = m_alias_options.find (alias);
2191 if (pos != m_alias_options.end())
2192 ret_val = pos->second;
2193 }
2194
2195 return ret_val;
2196}
2197
2198void
2199CommandInterpreter::RemoveAliasOptions (const char *alias_name)
2200{
2201 OptionArgMap::iterator pos = m_alias_options.find(alias_name);
2202 if (pos != m_alias_options.end())
2203 {
2204 m_alias_options.erase (pos);
2205 }
2206}
2207
2208void
2209CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
2210{
2211 m_alias_options[alias_name] = option_arg_vector_sp;
2212}
2213
2214bool
2215CommandInterpreter::HasCommands ()
2216{
2217 return (!m_command_dict.empty());
2218}
2219
2220bool
2221CommandInterpreter::HasAliases ()
2222{
2223 return (!m_alias_dict.empty());
2224}
2225
2226bool
2227CommandInterpreter::HasUserCommands ()
2228{
2229 return (!m_user_dict.empty());
2230}
2231
2232bool
2233CommandInterpreter::HasAliasOptions ()
2234{
2235 return (!m_alias_options.empty());
2236}
2237
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002238void
Caroline Tice4ab31c92010-10-12 21:57:09 +00002239CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
2240 const char *alias_name,
2241 Args &cmd_args,
Caroline Ticed9d63362010-12-07 19:58:26 +00002242 std::string &raw_input_string,
Caroline Tice4ab31c92010-10-12 21:57:09 +00002243 CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002244{
2245 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
Caroline Ticed9d63362010-12-07 19:58:26 +00002246
2247 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002248
Caroline Ticed9d63362010-12-07 19:58:26 +00002249 // Make sure that the alias name is the 0th element in cmd_args
2250 std::string alias_name_str = alias_name;
2251 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
2252 cmd_args.Unshift (alias_name);
2253
2254 Args new_args (alias_cmd_obj->GetCommandName());
2255 if (new_args.GetArgumentCount() == 2)
2256 new_args.Shift();
2257
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002258 if (option_arg_vector_sp.get())
2259 {
Caroline Ticed9d63362010-12-07 19:58:26 +00002260 if (wants_raw_input)
2261 {
2262 // We have a command that both has command options and takes raw input. Make *sure* it has a
2263 // " -- " in the right place in the raw_input_string.
2264 size_t pos = raw_input_string.find(" -- ");
2265 if (pos == std::string::npos)
2266 {
2267 // None found; assume it goes at the beginning of the raw input string
2268 raw_input_string.insert (0, " -- ");
2269 }
2270 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002271
2272 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
Greg Claytonc7bece562013-01-25 18:06:21 +00002273 const size_t old_size = cmd_args.GetArgumentCount();
Caroline Tice4ab31c92010-10-12 21:57:09 +00002274 std::vector<bool> used (old_size + 1, false);
2275
2276 used[0] = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002277
2278 for (int i = 0; i < option_arg_vector->size(); ++i)
2279 {
2280 OptionArgPair option_pair = (*option_arg_vector)[i];
Caroline Ticed9d63362010-12-07 19:58:26 +00002281 OptionArgValue value_pair = option_pair.second;
2282 int value_type = value_pair.first;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002283 std::string option = option_pair.first;
Caroline Ticed9d63362010-12-07 19:58:26 +00002284 std::string value = value_pair.second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002285 if (option.compare ("<argument>") == 0)
Caroline Ticed9d63362010-12-07 19:58:26 +00002286 {
2287 if (!wants_raw_input
2288 || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
2289 new_args.AppendArgument (value.c_str());
2290 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002291 else
2292 {
Caroline Ticed9d63362010-12-07 19:58:26 +00002293 if (value_type != optional_argument)
2294 new_args.AppendArgument (option.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002295 if (value.compare ("<no-argument>") != 0)
2296 {
2297 int index = GetOptionArgumentPosition (value.c_str());
2298 if (index == 0)
Caroline Ticed9d63362010-12-07 19:58:26 +00002299 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002300 // value was NOT a positional argument; must be a real value
Caroline Ticed9d63362010-12-07 19:58:26 +00002301 if (value_type != optional_argument)
2302 new_args.AppendArgument (value.c_str());
2303 else
2304 {
2305 char buffer[255];
2306 ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
2307 new_args.AppendArgument (buffer);
2308 }
2309
2310 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002311 else if (index >= cmd_args.GetArgumentCount())
2312 {
2313 result.AppendErrorWithFormat
2314 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
2315 index);
2316 result.SetStatus (eReturnStatusFailed);
2317 return;
2318 }
2319 else
2320 {
Caroline Ticed9d63362010-12-07 19:58:26 +00002321 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2322 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
2323 if (strpos != std::string::npos)
2324 {
2325 raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
2326 }
2327
2328 if (value_type != optional_argument)
2329 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
2330 else
2331 {
2332 char buffer[255];
2333 ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
2334 cmd_args.GetArgumentAtIndex (index));
2335 new_args.AppendArgument (buffer);
2336 }
Caroline Tice4ab31c92010-10-12 21:57:09 +00002337 used[index] = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002338 }
2339 }
2340 }
2341 }
2342
2343 for (int j = 0; j < cmd_args.GetArgumentCount(); ++j)
2344 {
Caroline Ticed9d63362010-12-07 19:58:26 +00002345 if (!used[j] && !wants_raw_input)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002346 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
2347 }
2348
2349 cmd_args.Clear();
2350 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2351 }
2352 else
2353 {
2354 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Caroline Ticed9d63362010-12-07 19:58:26 +00002355 // This alias was not created with any options; nothing further needs to be done, unless it is a command that
2356 // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
2357 // input string.
2358 if (wants_raw_input)
2359 {
2360 cmd_args.Clear();
2361 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2362 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002363 return;
2364 }
2365
2366 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2367 return;
2368}
2369
2370
2371int
2372CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
2373{
2374 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
2375 // of zero.
2376
2377 char *cptr = (char *) in_string;
2378
2379 // Does it start with '%'
2380 if (cptr[0] == '%')
2381 {
2382 ++cptr;
2383
2384 // Is the rest of it entirely digits?
2385 if (isdigit (cptr[0]))
2386 {
2387 const char *start = cptr;
2388 while (isdigit (cptr[0]))
2389 ++cptr;
2390
2391 // We've gotten to the end of the digits; are we at the end of the string?
2392 if (cptr[0] == '\0')
2393 position = atoi (start);
2394 }
2395 }
2396
2397 return position;
2398}
2399
2400void
2401CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
2402{
Jim Ingham16e0c682011-08-12 23:34:31 +00002403 FileSpec init_file;
Greg Clayton14a35512011-09-11 00:01:44 +00002404 if (in_cwd)
Jim Ingham16e0c682011-08-12 23:34:31 +00002405 {
Greg Clayton14a35512011-09-11 00:01:44 +00002406 // In the current working directory we don't load any program specific
2407 // .lldbinit files, we only look for a "./.lldbinit" file.
2408 if (m_skip_lldbinit_files)
2409 return;
2410
2411 init_file.SetFile ("./.lldbinit", true);
Jim Ingham16e0c682011-08-12 23:34:31 +00002412 }
Greg Clayton14a35512011-09-11 00:01:44 +00002413 else
Jim Ingham16e0c682011-08-12 23:34:31 +00002414 {
Greg Clayton14a35512011-09-11 00:01:44 +00002415 // If we aren't looking in the current working directory we are looking
2416 // in the home directory. We will first see if there is an application
2417 // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
2418 // "-" and the name of the program. If this file doesn't exist, we fall
2419 // back to just the "~/.lldbinit" file. We also obey any requests to not
2420 // load the init files.
2421 const char *init_file_path = "~/.lldbinit";
2422
2423 if (m_skip_app_init_files == false)
2424 {
2425 FileSpec program_file_spec (Host::GetProgramFileSpec());
2426 const char *program_name = program_file_spec.GetFilename().AsCString();
Jim Ingham16e0c682011-08-12 23:34:31 +00002427
Greg Clayton14a35512011-09-11 00:01:44 +00002428 if (program_name)
2429 {
2430 char program_init_file_name[PATH_MAX];
2431 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name);
2432 init_file.SetFile (program_init_file_name, true);
2433 if (!init_file.Exists())
2434 init_file.Clear();
2435 }
2436 }
2437
2438 if (!init_file && !m_skip_lldbinit_files)
2439 init_file.SetFile (init_file_path, true);
2440 }
2441
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002442 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
2443 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
2444
2445 if (init_file.Exists())
2446 {
Jim Inghame16c50a2011-02-18 00:54:25 +00002447 ExecutionContext *exe_ctx = NULL; // We don't have any context yet.
2448 bool stop_on_continue = true;
2449 bool stop_on_error = false;
2450 bool echo_commands = false;
2451 bool print_results = false;
2452
Enrico Granata5f5ab602012-05-31 01:09:06 +00002453 HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, eLazyBoolNo, result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002454 }
2455 else
2456 {
2457 // nothing to be done if the file doesn't exist
2458 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2459 }
2460}
2461
Greg Clayton8b82f082011-04-12 05:54:46 +00002462PlatformSP
2463CommandInterpreter::GetPlatform (bool prefer_target_platform)
2464{
2465 PlatformSP platform_sp;
Greg Claytonc14ee322011-09-22 04:58:26 +00002466 if (prefer_target_platform)
2467 {
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00002468 ExecutionContext exe_ctx(GetExecutionContext());
2469 Target *target = exe_ctx.GetTargetPtr();
Greg Claytonc14ee322011-09-22 04:58:26 +00002470 if (target)
2471 platform_sp = target->GetPlatform();
2472 }
Greg Clayton8b82f082011-04-12 05:54:46 +00002473
2474 if (!platform_sp)
2475 platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
2476 return platform_sp;
2477}
2478
Jim Inghame16c50a2011-02-18 00:54:25 +00002479void
Jim Inghambad87fe2011-03-11 01:51:49 +00002480CommandInterpreter::HandleCommands (const StringList &commands,
Jim Inghame16c50a2011-02-18 00:54:25 +00002481 ExecutionContext *override_context,
2482 bool stop_on_continue,
2483 bool stop_on_error,
2484 bool echo_commands,
2485 bool print_results,
Enrico Granata5f5ab602012-05-31 01:09:06 +00002486 LazyBool add_to_history,
Jim Inghame16c50a2011-02-18 00:54:25 +00002487 CommandReturnObject &result)
2488{
2489 size_t num_lines = commands.GetSize();
Jim Inghame16c50a2011-02-18 00:54:25 +00002490
2491 // If we are going to continue past a "continue" then we need to run the commands synchronously.
2492 // Make sure you reset this value anywhere you return from the function.
2493
2494 bool old_async_execution = m_debugger.GetAsyncExecution();
2495
2496 // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
2497 // cause series of commands that change the context, then do an operation that relies on that context to fail.
2498
2499 if (override_context != NULL)
Greg Clayton8b82f082011-04-12 05:54:46 +00002500 UpdateExecutionContext (override_context);
Jim Inghame16c50a2011-02-18 00:54:25 +00002501
2502 if (!stop_on_continue)
2503 {
2504 m_debugger.SetAsyncExecution (false);
2505 }
2506
2507 for (int idx = 0; idx < num_lines; idx++)
2508 {
2509 const char *cmd = commands.GetStringAtIndex(idx);
2510 if (cmd[0] == '\0')
2511 continue;
2512
Jim Inghame16c50a2011-02-18 00:54:25 +00002513 if (echo_commands)
2514 {
2515 result.AppendMessageWithFormat ("%s %s\n",
2516 GetPrompt(),
2517 cmd);
2518 }
2519
Greg Clayton9d0402b2011-02-20 02:15:07 +00002520 CommandReturnObject tmp_result;
Johnny Chen80fdd7c2011-10-05 00:42:59 +00002521 // If override_context is not NULL, pass no_context_switching = true for
2522 // HandleCommand() since we updated our context already.
Jim Ingham076b7fc2013-05-02 23:15:37 +00002523
2524 // We might call into a regex or alias command, in which case the add_to_history will get lost. This
2525 // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
2526 if (!add_to_history)
2527 m_command_source_depth++;
Enrico Granata5f5ab602012-05-31 01:09:06 +00002528 bool success = HandleCommand(cmd, add_to_history, tmp_result,
Johnny Chen80fdd7c2011-10-05 00:42:59 +00002529 NULL, /* override_context */
2530 true, /* repeat_on_empty_command */
2531 override_context != NULL /* no_context_switching */);
Jim Ingham076b7fc2013-05-02 23:15:37 +00002532 if (!add_to_history)
2533 m_command_source_depth--;
Jim Inghame16c50a2011-02-18 00:54:25 +00002534
2535 if (print_results)
2536 {
2537 if (tmp_result.Succeeded())
Jim Ingham85e8b812011-02-19 02:53:09 +00002538 result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
Jim Inghame16c50a2011-02-18 00:54:25 +00002539 }
2540
2541 if (!success || !tmp_result.Succeeded())
2542 {
Jim Inghama5038812012-04-24 02:25:07 +00002543 const char *error_msg = tmp_result.GetErrorData();
2544 if (error_msg == NULL || error_msg[0] == '\0')
2545 error_msg = "<unknown error>.\n";
Jim Inghame16c50a2011-02-18 00:54:25 +00002546 if (stop_on_error)
2547 {
Jim Inghama5038812012-04-24 02:25:07 +00002548 result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' failed with %s",
2549 idx, cmd, error_msg);
Jim Inghame16c50a2011-02-18 00:54:25 +00002550 result.SetStatus (eReturnStatusFailed);
2551 m_debugger.SetAsyncExecution (old_async_execution);
2552 return;
2553 }
2554 else if (print_results)
2555 {
Jim Inghama5038812012-04-24 02:25:07 +00002556 result.AppendMessageWithFormat ("Command #%d '%s' failed with %s",
Jim Inghame16c50a2011-02-18 00:54:25 +00002557 idx + 1,
2558 cmd,
Jim Inghama5038812012-04-24 02:25:07 +00002559 error_msg);
Jim Inghame16c50a2011-02-18 00:54:25 +00002560 }
2561 }
2562
Caroline Tice969ed3d2011-05-02 20:41:46 +00002563 if (result.GetImmediateOutputStream())
2564 result.GetImmediateOutputStream()->Flush();
2565
2566 if (result.GetImmediateErrorStream())
2567 result.GetImmediateErrorStream()->Flush();
2568
Jim Inghame16c50a2011-02-18 00:54:25 +00002569 // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
2570 // could be running (for instance in Breakpoint Commands.
2571 // So we check the return value to see if it is has running in it.
2572 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
2573 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
2574 {
2575 if (stop_on_continue)
2576 {
2577 // If we caused the target to proceed, and we're going to stop in that case, set the
2578 // status in our real result before returning. This is an error if the continue was not the
2579 // last command in the set of commands to be run.
2580 if (idx != num_lines - 1)
2581 result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' continued the target.\n",
2582 idx + 1, cmd);
2583 else
2584 result.AppendMessageWithFormat ("Command #%d '%s' continued the target.\n", idx + 1, cmd);
2585
2586 result.SetStatus(tmp_result.GetStatus());
2587 m_debugger.SetAsyncExecution (old_async_execution);
2588
2589 return;
2590 }
2591 }
2592
2593 }
2594
2595 result.SetStatus (eReturnStatusSuccessFinishResult);
2596 m_debugger.SetAsyncExecution (old_async_execution);
2597
2598 return;
2599}
2600
2601void
2602CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
2603 ExecutionContext *context,
2604 bool stop_on_continue,
2605 bool stop_on_error,
2606 bool echo_command,
2607 bool print_result,
Enrico Granata5f5ab602012-05-31 01:09:06 +00002608 LazyBool add_to_history,
Jim Inghame16c50a2011-02-18 00:54:25 +00002609 CommandReturnObject &result)
2610{
2611 if (cmd_file.Exists())
2612 {
2613 bool success;
2614 StringList commands;
2615 success = commands.ReadFileLines(cmd_file);
2616 if (!success)
2617 {
2618 result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString());
2619 result.SetStatus (eReturnStatusFailed);
2620 return;
2621 }
Enrico Granata5f5ab602012-05-31 01:09:06 +00002622 m_command_source_depth++;
2623 HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, add_to_history, result);
2624 m_command_source_depth--;
Jim Inghame16c50a2011-02-18 00:54:25 +00002625 }
2626 else
2627 {
2628 result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
2629 cmd_file.GetFilename().AsCString());
2630 result.SetStatus (eReturnStatusFailed);
2631 return;
2632 }
2633}
2634
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002635ScriptInterpreter *
Enrico Granatab5887262012-10-29 21:18:03 +00002636CommandInterpreter::GetScriptInterpreter (bool can_create)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002637{
Enrico Granatab5887262012-10-29 21:18:03 +00002638 if (m_script_interpreter_ap.get() != NULL)
2639 return m_script_interpreter_ap.get();
2640
2641 if (!can_create)
2642 return NULL;
2643
Enrico Granataa29bdad2012-07-10 18:23:48 +00002644 // <rdar://problem/11751427>
2645 // we need to protect the initialization of the script interpreter
2646 // otherwise we could end up with two threads both trying to create
2647 // their instance of it, and for some languages (e.g. Python)
2648 // this is a bulletproof recipe for disaster!
2649 // this needs to be a function-level static because multiple Debugger instances living in the same process
2650 // still need to be isolated and not try to initialize Python concurrently
Enrico Granata8b95df22012-07-10 19:04:14 +00002651 static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
2652 Mutex::Locker interpreter_lock(g_interpreter_mutex);
Enrico Granataa29bdad2012-07-10 18:23:48 +00002653
Greg Clayton5160ce52013-03-27 23:08:40 +00002654 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Enrico Granatab5887262012-10-29 21:18:03 +00002655 if (log)
2656 log->Printf("Initializing the ScriptInterpreter now\n");
Greg Clayton66111032010-06-23 01:19:29 +00002657
Caroline Tice2f88aad2011-01-14 00:29:16 +00002658 lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
2659 switch (script_lang)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002660 {
Greg Claytondce502e2011-11-04 03:34:56 +00002661 case eScriptLanguagePython:
2662#ifndef LLDB_DISABLE_PYTHON
2663 m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
2664 break;
2665#else
2666 // Fall through to the None case when python is disabled
2667#endif
Caroline Tice2f88aad2011-01-14 00:29:16 +00002668 case eScriptLanguageNone:
2669 m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
2670 break;
Caroline Tice2f88aad2011-01-14 00:29:16 +00002671 };
2672
2673 return m_script_interpreter_ap.get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002674}
2675
2676
2677
2678bool
2679CommandInterpreter::GetSynchronous ()
2680{
2681 return m_synchronous_execution;
2682}
2683
2684void
2685CommandInterpreter::SetSynchronous (bool value)
2686{
Johnny Chenc066ab42010-10-14 01:22:03 +00002687 m_synchronous_execution = value;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002688}
2689
2690void
2691CommandInterpreter::OutputFormattedHelpText (Stream &strm,
2692 const char *word_text,
2693 const char *separator,
2694 const char *help_text,
Greg Claytonc7bece562013-01-25 18:06:21 +00002695 size_t max_word_len)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002696{
Greg Claytona7015092010-09-18 01:14:36 +00002697 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2698
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002699 int indent_size = max_word_len + strlen (separator) + 2;
2700
2701 strm.IndentMore (indent_size);
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002702
2703 StreamString text_strm;
Greg Claytonc7bece562013-01-25 18:06:21 +00002704 text_strm.Printf ("%-*s %s %s", (int)max_word_len, word_text, separator, help_text);
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002705
2706 size_t len = text_strm.GetSize();
2707 const char *text = text_strm.GetData();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002708 if (text[len - 1] == '\n')
Greg Claytonbfe5f3b2011-02-18 01:44:25 +00002709 {
2710 text_strm.EOL();
2711 len = text_strm.GetSize();
2712 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002713
2714 if (len < max_columns)
2715 {
2716 // Output it as a single line.
2717 strm.Printf ("%s", text);
2718 }
2719 else
2720 {
2721 // We need to break it up into multiple lines.
2722 bool first_line = true;
2723 int text_width;
Greg Claytonc7bece562013-01-25 18:06:21 +00002724 size_t start = 0;
2725 size_t end = start;
2726 const size_t final_end = strlen (text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002727
2728 while (end < final_end)
2729 {
2730 if (first_line)
2731 text_width = max_columns - 1;
2732 else
2733 text_width = max_columns - indent_size - 1;
2734
2735 // Don't start the 'text' on a space, since we're already outputting the indentation.
2736 if (!first_line)
2737 {
2738 while ((start < final_end) && (text[start] == ' '))
2739 start++;
2740 }
2741
2742 end = start + text_width;
2743 if (end > final_end)
2744 end = final_end;
2745 else
2746 {
2747 // If we're not at the end of the text, make sure we break the line on white space.
2748 while (end > start
2749 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
2750 end--;
Greg Clayton67cc0632012-08-22 17:17:09 +00002751 assert (end > 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002752 }
2753
Greg Claytonc7bece562013-01-25 18:06:21 +00002754 const size_t sub_len = end - start;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002755 if (start != 0)
2756 strm.EOL();
2757 if (!first_line)
2758 strm.Indent();
2759 else
2760 first_line = false;
2761 assert (start <= final_end);
2762 assert (start + sub_len <= final_end);
2763 if (sub_len > 0)
2764 strm.Write (text + start, sub_len);
2765 start = end + 1;
2766 }
2767 }
2768 strm.EOL();
2769 strm.IndentLess(indent_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002770}
2771
2772void
Enrico Granata82a7d982011-07-07 00:38:40 +00002773CommandInterpreter::OutputHelpText (Stream &strm,
2774 const char *word_text,
2775 const char *separator,
2776 const char *help_text,
2777 uint32_t max_word_len)
2778{
2779 int indent_size = max_word_len + strlen (separator) + 2;
2780
2781 strm.IndentMore (indent_size);
2782
2783 StreamString text_strm;
2784 text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
2785
2786 const uint32_t max_columns = m_debugger.GetTerminalWidth();
Enrico Granata82a7d982011-07-07 00:38:40 +00002787
2788 size_t len = text_strm.GetSize();
2789 const char *text = text_strm.GetData();
2790
2791 uint32_t chars_left = max_columns;
2792
2793 for (uint32_t i = 0; i < len; i++)
2794 {
2795 if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
2796 {
Enrico Granata82a7d982011-07-07 00:38:40 +00002797 chars_left = max_columns - indent_size;
2798 strm.EOL();
2799 strm.Indent();
2800 }
2801 else
2802 {
2803 strm.PutChar(text[i]);
2804 chars_left--;
2805 }
2806
2807 }
2808
2809 strm.EOL();
2810 strm.IndentLess(indent_size);
2811}
2812
2813void
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002814CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
Jim Inghamaf3753e2013-05-17 01:30:37 +00002815 StringList &commands_help, bool search_builtin_commands, bool search_user_commands)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002816{
2817 CommandObject::CommandMap::const_iterator pos;
2818
Jim Inghamaf3753e2013-05-17 01:30:37 +00002819 if (search_builtin_commands)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002820 {
Jim Inghamaf3753e2013-05-17 01:30:37 +00002821 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002822 {
Jim Inghamaf3753e2013-05-17 01:30:37 +00002823 const char *command_name = pos->first.c_str();
2824 CommandObject *cmd_obj = pos->second.get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002825
Jim Inghamaf3753e2013-05-17 01:30:37 +00002826 if (cmd_obj->HelpTextContainsWord (search_word))
2827 {
2828 commands_found.AppendString (command_name);
2829 commands_help.AppendString (cmd_obj->GetHelp());
2830 }
2831
2832 if (cmd_obj->IsMultiwordObject())
2833 cmd_obj->AproposAllSubCommands (command_name,
2834 search_word,
2835 commands_found,
2836 commands_help);
2837
2838 }
2839 }
2840
2841 if (search_user_commands)
2842 {
2843 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
2844 {
2845 const char *command_name = pos->first.c_str();
2846 CommandObject *cmd_obj = pos->second.get();
2847
2848 if (cmd_obj->HelpTextContainsWord (search_word))
2849 {
2850 commands_found.AppendString (command_name);
2851 commands_help.AppendString (cmd_obj->GetHelp());
2852 }
2853
2854 if (cmd_obj->IsMultiwordObject())
2855 cmd_obj->AproposAllSubCommands (command_name,
2856 search_word,
2857 commands_found,
2858 commands_help);
2859
2860 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002861 }
2862}
Greg Clayton8b82f082011-04-12 05:54:46 +00002863
2864
2865void
2866CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
2867{
Greg Clayton8b82f082011-04-12 05:54:46 +00002868 if (override_context != NULL)
2869 {
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00002870 m_exe_ctx_ref = *override_context;
Greg Clayton8b82f082011-04-12 05:54:46 +00002871 }
2872 else
2873 {
Greg Clayton4e0fe8a2012-07-12 20:32:19 +00002874 const bool adopt_selected = true;
2875 m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
Greg Clayton8b82f082011-04-12 05:54:46 +00002876 }
2877}