1 //===-- CommandInterpreter.cpp ----------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/lldb-python.h"
11
12 #include <string>
13 #include <vector>
14
15 #include <getopt.h>
16 #include <stdlib.h>
17
18 #include "CommandObjectScript.h"
19 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
20
21 #include "../Commands/CommandObjectApropos.h"
22 #include "../Commands/CommandObjectArgs.h"
23 #include "../Commands/CommandObjectBreakpoint.h"
24 #include "../Commands/CommandObjectDisassemble.h"
25 #include "../Commands/CommandObjectExpression.h"
26 #include "../Commands/CommandObjectFrame.h"
27 #include "../Commands/CommandObjectHelp.h"
28 #include "../Commands/CommandObjectLog.h"
29 #include "../Commands/CommandObjectMemory.h"
30 #include "../Commands/CommandObjectPlatform.h"
31 #include "../Commands/CommandObjectPlugin.h"
32 #include "../Commands/CommandObjectProcess.h"
33 #include "../Commands/CommandObjectQuit.h"
34 #include "../Commands/CommandObjectRegister.h"
35 #include "../Commands/CommandObjectSettings.h"
36 #include "../Commands/CommandObjectSource.h"
37 #include "../Commands/CommandObjectCommands.h"
38 #include "../Commands/CommandObjectSyntax.h"
39 #include "../Commands/CommandObjectTarget.h"
40 #include "../Commands/CommandObjectThread.h"
41 #include "../Commands/CommandObjectType.h"
42 #include "../Commands/CommandObjectVersion.h"
43 #include "../Commands/CommandObjectWatchpoint.h"
44
45
46 #include "lldb/Core/Debugger.h"
47 #include "lldb/Core/InputReader.h"
48 #include "lldb/Core/Log.h"
49 #include "lldb/Core/Stream.h"
50 #include "lldb/Core/Timer.h"
51
52 #include "lldb/Host/Host.h"
53
54 #include "lldb/Interpreter/Args.h"
55 #include "lldb/Interpreter/CommandCompletions.h"
56 #include "lldb/Interpreter/CommandInterpreter.h"
57 #include "lldb/Interpreter/CommandReturnObject.h"
58 #include "lldb/Interpreter/Options.h"
59 #include "lldb/Interpreter/ScriptInterpreterNone.h"
60 #include "lldb/Interpreter/ScriptInterpreterPython.h"
61
62
63 #include "lldb/Target/Process.h"
64 #include "lldb/Target/Thread.h"
65 #include "lldb/Target/TargetList.h"
66
67 #include "lldb/Utility/CleanUp.h"
68
69 using namespace lldb;
70 using namespace lldb_private;
71
72
73 static PropertyDefinition
74 g_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." },
77 { "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." },
78 { "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." },
79 { NULL , OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL }
80 };
81
82 enum
83 {
84 ePropertyExpandRegexAliases = 0,
85 ePropertyPromptOnQuit = 1,
86 ePropertyStopCmdSourceOnError = 2
87 };
88
89 ConstString &
GetStaticBroadcasterClass()90 CommandInterpreter::GetStaticBroadcasterClass ()
91 {
92 static ConstString class_name ("lldb.commandInterpreter");
93 return class_name;
94 }
95
CommandInterpreter(Debugger & debugger,ScriptLanguage script_language,bool synchronous_execution)96 CommandInterpreter::CommandInterpreter
97 (
98 Debugger &debugger,
99 ScriptLanguage script_language,
100 bool synchronous_execution
101 ) :
102 Broadcaster (&debugger, "lldb.command-interpreter"),
103 Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
104 m_debugger (debugger),
105 m_synchronous_execution (synchronous_execution),
106 m_skip_lldbinit_files (false),
107 m_skip_app_init_files (false),
108 m_script_interpreter_ap (),
109 m_comment_char ('#'),
110 m_batch_command_mode (false),
111 m_truncation_warning(eNoTruncation),
112 m_command_source_depth (0)
113 {
114 debugger.SetScriptLanguage (script_language);
115 SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
116 SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
117 SetEventName (eBroadcastBitQuitCommandReceived, "quit");
118 CheckInWithManager ();
119 m_collection_sp->Initialize (g_properties);
120 }
121
122 bool
GetExpandRegexAliases() const123 CommandInterpreter::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
129 bool
GetPromptOnQuit() const130 CommandInterpreter::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 }
135
136 bool
GetStopCmdSourceOnError() const137 CommandInterpreter::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
143 void
Initialize()144 CommandInterpreter::Initialize ()
145 {
146 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
147
148 CommandReturnObject result;
149
150 LoadCommandDictionary ();
151
152 // Set up some initial aliases.
153 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 }
159
160 cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
161 if (cmd_obj_sp)
162 {
163 AddAlias ("attach", cmd_obj_sp);
164 }
165
166 cmd_obj_sp = GetCommandSPExact ("process detach",false);
167 if (cmd_obj_sp)
168 {
169 AddAlias ("detach", cmd_obj_sp);
170 }
171
172 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
183 cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
184 if (cmd_obj_sp)
185 AddAlias ("tbreak", cmd_obj_sp);
186
187 cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
188 if (cmd_obj_sp)
189 {
190 AddAlias ("stepi", cmd_obj_sp);
191 AddAlias ("si", cmd_obj_sp);
192 }
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 }
200
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 {
218 AddAlias ("finish", cmd_obj_sp);
219 }
220
221 cmd_obj_sp = GetCommandSPExact ("frame select", false);
222 if (cmd_obj_sp)
223 {
224 AddAlias ("f", cmd_obj_sp);
225 }
226
227 cmd_obj_sp = GetCommandSPExact ("thread select", false);
228 if (cmd_obj_sp)
229 {
230 AddAlias ("t", cmd_obj_sp);
231 }
232
233 cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
234 if (cmd_obj_sp)
235 {
236 AddAlias ("l", cmd_obj_sp);
237 AddAlias ("list", cmd_obj_sp);
238 }
239
240 cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
241 if (cmd_obj_sp)
242 {
243 AddAlias ("env", cmd_obj_sp);
244 }
245
246 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
258 cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
259 if (cmd_obj_sp)
260 AddAlias ("display", cmd_obj_sp);
261
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
271
272 cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
273 if (cmd_obj_sp)
274 AddAlias ("undisplay", cmd_obj_sp);
275
276 cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
277 if (cmd_obj_sp)
278 AddAlias ("bt", cmd_obj_sp);
279
280 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);
290
291 cmd_obj_sp = GetCommandSPExact ("expression", false);
292 if (cmd_obj_sp)
293 {
294 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
295 AddAlias ("p", cmd_obj_sp);
296 AddAlias ("print", cmd_obj_sp);
297 AddAlias ("call", cmd_obj_sp);
298 AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp);
299 AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp);
300 AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp);
301
302 alias_arguments_vector_sp.reset (new OptionArgVector);
303 ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp);
304 AddAlias ("po", cmd_obj_sp);
305 AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
306 }
307
308 cmd_obj_sp = GetCommandSPExact ("process kill", false);
309 if (cmd_obj_sp)
310 {
311 AddAlias ("kill", cmd_obj_sp);
312 }
313
314 cmd_obj_sp = GetCommandSPExact ("process launch", false);
315 if (cmd_obj_sp)
316 {
317 alias_arguments_vector_sp.reset (new OptionArgVector);
318 #if defined (__arm__)
319 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
320 #else
321 ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=/bin/bash --", alias_arguments_vector_sp);
322 #endif
323 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 }
328
329 cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
330 if (cmd_obj_sp)
331 {
332 AddAlias ("add-dsym", cmd_obj_sp);
333 }
334
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);
340 AddAlias ("rbreak", cmd_obj_sp);
341 AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp);
342 }
343 }
344
345 const char *
ProcessEmbeddedScriptCommands(const char * arg)346 CommandInterpreter::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
361 void
LoadCommandDictionary()362 CommandInterpreter::LoadCommandDictionary ()
363 {
364 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
365
366 lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
367
368 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this));
369 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
370 m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
371 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
372 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
373 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
374 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this));
375 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this));
376 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this));
377 m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this));
378 m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this));
379 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
380 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this));
381 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this));
382 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language));
383 m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
384 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this));
385 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
386 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this));
387 m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this));
388 m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this));
389 m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
390
391 const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
392 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
393 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
394 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
395 {"^(-.*)$", "breakpoint set %1"},
396 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
397 {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"},
398 {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}};
399
400 size_t num_regexes = sizeof break_regexes/sizeof(char *[2]);
401
402 std::unique_ptr<CommandObjectRegexCommand>
403 break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
404 "_regexp-break",
405 "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
406 "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
407 2,
408 CommandCompletions::eSymbolCompletion |
409 CommandCompletions::eSourceFileCompletion));
410
411 if (break_regex_cmd_ap.get())
412 {
413 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)
423 {
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 }
428
429 std::unique_ptr<CommandObjectRegexCommand>
430 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.",
433 "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
434 2,
435 CommandCompletions::eSymbolCompletion |
436 CommandCompletions::eSourceFileCompletion));
437
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
460 std::unique_ptr<CommandObjectRegexCommand>
461 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.",
464 "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]",
465 2));
466 if (attach_regex_cmd_ap.get())
467 {
468 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"))
472 {
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
478 std::unique_ptr<CommandObjectRegexCommand>
479 down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
480 "_regexp-down",
481 "Go down \"n\" frames in the stack (1 frame by default).",
482 "_regexp-down [n]", 2));
483 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
493 std::unique_ptr<CommandObjectRegexCommand>
494 up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
495 "_regexp-up",
496 "Go up \"n\" frames in the stack (1 frame by default).",
497 "_regexp-up [n]", 2));
498 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 }
507
508 std::unique_ptr<CommandObjectRegexCommand>
509 display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
510 "_regexp-display",
511 "Add an expression evaluation stop-hook.",
512 "_regexp-display expression", 2));
513 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
522 std::unique_ptr<CommandObjectRegexCommand>
523 undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
524 "_regexp-undisplay",
525 "Remove an expression evaluation stop-hook.",
526 "_regexp-undisplay stop-hook-number", 2));
527 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
536 std::unique_ptr<CommandObjectRegexCommand>
537 connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this,
538 "gdb-remote",
539 "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.",
540 "gdb-remote [<hostname>:]<portnum>", 2));
541 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
551 std::unique_ptr<CommandObjectRegexCommand>
552 connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this,
553 "kdp-remote",
554 "Connect to a remote KDP server. udp port 41139 is the default port number.",
555 "kdp-remote <hostname>[:<portnum>]", 2));
556 if (connect_kdp_remote_cmd_ap.get())
557 {
558 if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
559 connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139"))
560 {
561 CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
562 m_command_dict[command_sp->GetCommandName ()] = command_sp;
563 }
564 }
565
566 std::unique_ptr<CommandObjectRegexCommand>
567 bt_regex_cmd_ap(new CommandObjectRegexCommand (*this,
568 "_regexp-bt",
569 "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
586 std::unique_ptr<CommandObjectRegexCommand>
587 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.",
590 "_regexp-list [<line>]\n_regexp-attach [<file>:<line>]\n_regexp-attach [<file>:<line>]",
591 2,
592 CommandCompletions::eSourceFileCompletion));
593 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") &&
598 list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") &&
599 list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") &&
600 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
608 std::unique_ptr<CommandObjectRegexCommand>
609 env_regex_cmd_ap(new CommandObjectRegexCommand (*this,
610 "_regexp-env",
611 "Implements a shortcut to viewing and setting environment variables.",
612 "_regexp-env\n_regexp-env FOO=BAR", 2));
613 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
623 }
624
625 int
GetCommandNamesMatchingPartialString(const char * cmd_str,bool include_aliases,StringList & matches)626 CommandInterpreter::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
639 CommandObjectSP
GetCommandSP(const char * cmd_cstr,bool include_aliases,bool exact,StringList * matches)640 CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
641 {
642 CommandObject::CommandMap::iterator pos;
643 CommandObjectSP command_sp;
644
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())
651 command_sp = pos->second;
652 }
653
654 if (include_aliases && HasAliases())
655 {
656 pos = m_alias_dict.find(cmd);
657 if (pos != m_alias_dict.end())
658 command_sp = pos->second;
659 }
660
661 if (HasUserCommands())
662 {
663 pos = m_user_dict.find(cmd);
664 if (pos != m_user_dict.end())
665 command_sp = pos->second;
666 }
667
668 if (!exact && !command_sp)
669 {
670 // 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
674 StringList local_matches;
675 if (matches == NULL)
676 matches = &local_matches;
677
678 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
685 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())
695 real_match_sp = pos->second;
696 }
697
698 if (include_aliases && HasAliases())
699 {
700 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
701
702 }
703
704 if (num_alias_matches == 1)
705 {
706 cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
707 pos = m_alias_dict.find(cmd);
708 if (pos != m_alias_dict.end())
709 alias_match_sp = pos->second;
710 }
711
712 if (HasUserCommands())
713 {
714 num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
715 }
716
717 if (num_user_matches == 1)
718 {
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())
723 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;
736 }
737 }
738 else if (matches && command_sp)
739 {
740 matches->AppendString (cmd_cstr);
741 }
742
743
744 return command_sp;
745 }
746
747 bool
AddCommand(const char * name,const lldb::CommandObjectSP & cmd_sp,bool can_replace)748 CommandInterpreter::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);
753 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)
757 return false;
758 m_command_dict[name_sstr] = cmd_sp;
759 return true;
760 }
761 return false;
762 }
763
764 bool
AddUserCommand(std::string name,const lldb::CommandObjectSP & cmd_sp,bool can_replace)765 CommandInterpreter::AddUserCommand (std::string name,
766 const lldb::CommandObjectSP &cmd_sp,
767 bool can_replace)
768 {
769 if (!name.empty())
770 {
771
772 const char* name_cstr = name.c_str();
773
774 // do not allow replacement of internal commands
775 if (CommandExists(name_cstr))
776 {
777 if (can_replace == false)
778 return false;
779 if (m_command_dict[name]->IsRemovable() == false)
780 return false;
781 }
782
783 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
791 m_user_dict[name] = cmd_sp;
792 return true;
793 }
794 return false;
795 }
796
797 CommandObjectSP
GetCommandSPExact(const char * cmd_cstr,bool include_aliases)798 CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
799 {
800 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 {
822 cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
823 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;
838 }
839
840 CommandObject *
GetCommandObjectExact(const char * cmd_cstr,bool include_aliases)841 CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
842 {
843 return GetCommandSPExact (cmd_cstr, include_aliases).get();
844 }
845
846 CommandObject *
GetCommandObject(const char * cmd_cstr,StringList * matches)847 CommandInterpreter::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)
855 return command_obj;
856
857 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
858
859 if (command_obj)
860 return command_obj;
861
862 // If there wasn't an exact match then look for an inexact one in just the commands
863 command_obj = GetCommandSP(cmd_cstr, false, false, NULL).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
868 if (command_obj)
869 {
870 if (matches)
871 matches->AppendString(command_obj->GetCommandName());
872 return command_obj;
873 }
874
875 return GetCommandSP(cmd_cstr, true, false, matches).get();
876 }
877
878 bool
CommandExists(const char * cmd)879 CommandInterpreter::CommandExists (const char *cmd)
880 {
881 return m_command_dict.find(cmd) != m_command_dict.end();
882 }
883
884 bool
ProcessAliasOptionsArgs(lldb::CommandObjectSP & cmd_obj_sp,const char * options_args,OptionArgVectorSP & option_arg_vector_sp)885 CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
886 const char *options_args,
887 OptionArgVectorSP &option_arg_vector_sp)
888 {
889 bool success = true;
890 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
891
892 if (!options_args || (strlen (options_args) < 1))
893 return true;
894
895 std::string options_string (options_args);
896 Args args (options_args);
897 CommandReturnObject result;
898 // Check to see if the command being aliased can take any command options.
899 Options *options = cmd_obj_sp->GetOptions ();
900 if (options)
901 {
902 // See if any options were specified as part of the alias; if so, handle them appropriately.
903 options->NotifyOptionParsingStarting ();
904 args.Unshift ("dummy_arg");
905 args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
906 args.Shift ();
907 if (result.Succeeded())
908 options->VerifyPartialOptions (result);
909 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
910 {
911 result.AppendError ("Unable to create requested alias.\n");
912 return false;
913 }
914 }
915
916 if (!options_string.empty())
917 {
918 if (cmd_obj_sp->WantsRawCommandString ())
919 option_arg_vector->push_back (OptionArgPair ("<argument>",
920 OptionArgValue (-1,
921 options_string)));
922 else
923 {
924 const size_t argc = args.GetArgumentCount();
925 for (size_t i = 0; i < argc; ++i)
926 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
927 option_arg_vector->push_back
928 (OptionArgPair ("<argument>",
929 OptionArgValue (-1,
930 std::string (args.GetArgumentAtIndex (i)))));
931 }
932 }
933
934 return success;
935 }
936
937 bool
GetAliasFullName(const char * cmd,std::string & full_name)938 CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
939 {
940 bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end());
941 if (exact_match)
942 {
943 full_name.assign(cmd);
944 return exact_match;
945 }
946 else
947 {
948 StringList matches;
949 size_t num_alias_matches;
950 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
951 if (num_alias_matches == 1)
952 {
953 // Make sure this isn't shadowing a command in the regular command space:
954 StringList regular_matches;
955 const bool include_aliases = false;
956 const bool exact = false;
957 CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, ®ular_matches));
958 if (cmd_obj_sp || regular_matches.GetSize() > 0)
959 return false;
960 else
961 {
962 full_name.assign (matches.GetStringAtIndex(0));
963 return true;
964 }
965 }
966 else
967 return false;
968 }
969 }
970
971 bool
AliasExists(const char * cmd)972 CommandInterpreter::AliasExists (const char *cmd)
973 {
974 return m_alias_dict.find(cmd) != m_alias_dict.end();
975 }
976
977 bool
UserCommandExists(const char * cmd)978 CommandInterpreter::UserCommandExists (const char *cmd)
979 {
980 return m_user_dict.find(cmd) != m_user_dict.end();
981 }
982
983 void
AddAlias(const char * alias_name,CommandObjectSP & command_obj_sp)984 CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
985 {
986 command_obj_sp->SetIsAlias (true);
987 m_alias_dict[alias_name] = command_obj_sp;
988 }
989
990 bool
RemoveAlias(const char * alias_name)991 CommandInterpreter::RemoveAlias (const char *alias_name)
992 {
993 CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
994 if (pos != m_alias_dict.end())
995 {
996 m_alias_dict.erase(pos);
997 return true;
998 }
999 return false;
1000 }
1001 bool
RemoveUser(const char * alias_name)1002 CommandInterpreter::RemoveUser (const char *alias_name)
1003 {
1004 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
1005 if (pos != m_user_dict.end())
1006 {
1007 m_user_dict.erase(pos);
1008 return true;
1009 }
1010 return false;
1011 }
1012
1013 void
GetAliasHelp(const char * alias_name,const char * command_name,StreamString & help_string)1014 CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
1015 {
1016 help_string.Printf ("'%s", command_name);
1017 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1018
1019 if (option_arg_vector_sp)
1020 {
1021 OptionArgVector *options = option_arg_vector_sp.get();
1022 for (size_t i = 0; i < options->size(); ++i)
1023 {
1024 OptionArgPair cur_option = (*options)[i];
1025 std::string opt = cur_option.first;
1026 OptionArgValue value_pair = cur_option.second;
1027 std::string value = value_pair.second;
1028 if (opt.compare("<argument>") == 0)
1029 {
1030 help_string.Printf (" %s", value.c_str());
1031 }
1032 else
1033 {
1034 help_string.Printf (" %s", opt.c_str());
1035 if ((value.compare ("<no-argument>") != 0)
1036 && (value.compare ("<need-argument") != 0))
1037 {
1038 help_string.Printf (" %s", value.c_str());
1039 }
1040 }
1041 }
1042 }
1043
1044 help_string.Printf ("'");
1045 }
1046
1047 size_t
FindLongestCommandWord(CommandObject::CommandMap & dict)1048 CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
1049 {
1050 CommandObject::CommandMap::const_iterator pos;
1051 CommandObject::CommandMap::const_iterator end = dict.end();
1052 size_t max_len = 0;
1053
1054 for (pos = dict.begin(); pos != end; ++pos)
1055 {
1056 size_t len = pos->first.size();
1057 if (max_len < len)
1058 max_len = len;
1059 }
1060 return max_len;
1061 }
1062
1063 void
GetHelp(CommandReturnObject & result,uint32_t cmd_types)1064 CommandInterpreter::GetHelp (CommandReturnObject &result,
1065 uint32_t cmd_types)
1066 {
1067 CommandObject::CommandMap::const_iterator pos;
1068 size_t max_len = FindLongestCommandWord (m_command_dict);
1069
1070 if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
1071 {
1072
1073 result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
1074 result.AppendMessage("");
1075
1076 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
1077 {
1078 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1079 max_len);
1080 }
1081 result.AppendMessage("");
1082
1083 }
1084
1085 if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
1086 {
1087 result.AppendMessage("The following is a list of your current command abbreviations "
1088 "(see 'help command alias' for more info):");
1089 result.AppendMessage("");
1090 max_len = FindLongestCommandWord (m_alias_dict);
1091
1092 for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
1093 {
1094 StreamString sstr;
1095 StreamString translation_and_help;
1096 std::string entry_name = pos->first;
1097 std::string second_entry = pos->second.get()->GetCommandName();
1098 GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
1099
1100 translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp());
1101 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
1102 translation_and_help.GetData(), max_len);
1103 }
1104 result.AppendMessage("");
1105 }
1106
1107 if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
1108 {
1109 result.AppendMessage ("The following is a list of your current user-defined commands:");
1110 result.AppendMessage("");
1111 max_len = FindLongestCommandWord (m_user_dict);
1112 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
1113 {
1114 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1115 max_len);
1116 }
1117 result.AppendMessage("");
1118 }
1119
1120 result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
1121 }
1122
1123 CommandObject *
GetCommandObjectForCommand(std::string & command_string)1124 CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
1125 {
1126 // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
1127 // eventually be invoked by the given command line.
1128
1129 CommandObject *cmd_obj = NULL;
1130 std::string white_space (" \t\v");
1131 size_t start = command_string.find_first_not_of (white_space);
1132 size_t end = 0;
1133 bool done = false;
1134 while (!done)
1135 {
1136 if (start != std::string::npos)
1137 {
1138 // Get the next word from command_string.
1139 end = command_string.find_first_of (white_space, start);
1140 if (end == std::string::npos)
1141 end = command_string.size();
1142 std::string cmd_word = command_string.substr (start, end - start);
1143
1144 if (cmd_obj == NULL)
1145 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
1146 // command or alias.
1147 cmd_obj = GetCommandObject (cmd_word.c_str());
1148 else if (cmd_obj->IsMultiwordObject ())
1149 {
1150 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
1151 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str());
1152 if (sub_cmd_obj)
1153 cmd_obj = sub_cmd_obj;
1154 else // cmd_word was not a valid sub-command word, so we are donee
1155 done = true;
1156 }
1157 else
1158 // We have a cmd_obj and it is not a multi-word object, so we are done.
1159 done = true;
1160
1161 // If we didn't find a valid command object, or our command object is not a multi-word object, or
1162 // we are at the end of the command_string, then we are done. Otherwise, find the start of the
1163 // next word.
1164
1165 if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
1166 done = true;
1167 else
1168 start = command_string.find_first_not_of (white_space, end);
1169 }
1170 else
1171 // Unable to find any more words.
1172 done = true;
1173 }
1174
1175 if (end == command_string.size())
1176 command_string.clear();
1177 else
1178 command_string = command_string.substr(end);
1179
1180 return cmd_obj;
1181 }
1182
1183 static const char *k_white_space = " \t\v";
1184 static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1185 static void
StripLeadingSpaces(std::string & s)1186 StripLeadingSpaces (std::string &s)
1187 {
1188 if (!s.empty())
1189 {
1190 size_t pos = s.find_first_not_of (k_white_space);
1191 if (pos == std::string::npos)
1192 s.clear();
1193 else if (pos == 0)
1194 return;
1195 s.erase (0, pos);
1196 }
1197 }
1198
1199 static size_t
FindArgumentTerminator(const std::string & s)1200 FindArgumentTerminator (const std::string &s)
1201 {
1202 const size_t s_len = s.size();
1203 size_t offset = 0;
1204 while (offset < s_len)
1205 {
1206 size_t pos = s.find ("--", offset);
1207 if (pos == std::string::npos)
1208 break;
1209 if (pos > 0)
1210 {
1211 if (isspace(s[pos-1]))
1212 {
1213 // Check if the string ends "\s--" (where \s is a space character)
1214 // or if we have "\s--\s".
1215 if ((pos + 2 >= s_len) || isspace(s[pos+2]))
1216 {
1217 return pos;
1218 }
1219 }
1220 }
1221 offset = pos + 2;
1222 }
1223 return std::string::npos;
1224 }
1225
1226 static bool
ExtractCommand(std::string & command_string,std::string & command,std::string & suffix,char & quote_char)1227 ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char "e_char)
1228 {
1229 command.clear();
1230 suffix.clear();
1231 StripLeadingSpaces (command_string);
1232
1233 bool result = false;
1234 quote_char = '\0';
1235
1236 if (!command_string.empty())
1237 {
1238 const char first_char = command_string[0];
1239 if (first_char == '\'' || first_char == '"')
1240 {
1241 quote_char = first_char;
1242 const size_t end_quote_pos = command_string.find (quote_char, 1);
1243 if (end_quote_pos == std::string::npos)
1244 {
1245 command.swap (command_string);
1246 command_string.erase ();
1247 }
1248 else
1249 {
1250 command.assign (command_string, 1, end_quote_pos - 1);
1251 if (end_quote_pos + 1 < command_string.size())
1252 command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
1253 else
1254 command_string.erase ();
1255 }
1256 }
1257 else
1258 {
1259 const size_t first_space_pos = command_string.find_first_of (k_white_space);
1260 if (first_space_pos == std::string::npos)
1261 {
1262 command.swap (command_string);
1263 command_string.erase();
1264 }
1265 else
1266 {
1267 command.assign (command_string, 0, first_space_pos);
1268 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
1269 }
1270 }
1271 result = true;
1272 }
1273
1274
1275 if (!command.empty())
1276 {
1277 // actual commands can't start with '-' or '_'
1278 if (command[0] != '-' && command[0] != '_')
1279 {
1280 size_t pos = command.find_first_not_of(k_valid_command_chars);
1281 if (pos > 0 && pos != std::string::npos)
1282 {
1283 suffix.assign (command.begin() + pos, command.end());
1284 command.erase (pos);
1285 }
1286 }
1287 }
1288
1289 return result;
1290 }
1291
1292 CommandObject *
BuildAliasResult(const char * alias_name,std::string & raw_input_string,std::string & alias_result,CommandReturnObject & result)1293 CommandInterpreter::BuildAliasResult (const char *alias_name,
1294 std::string &raw_input_string,
1295 std::string &alias_result,
1296 CommandReturnObject &result)
1297 {
1298 CommandObject *alias_cmd_obj = NULL;
1299 Args cmd_args (raw_input_string.c_str());
1300 alias_cmd_obj = GetCommandObject (alias_name);
1301 StreamString result_str;
1302
1303 if (alias_cmd_obj)
1304 {
1305 std::string alias_name_str = alias_name;
1306 if ((cmd_args.GetArgumentCount() == 0)
1307 || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
1308 cmd_args.Unshift (alias_name);
1309
1310 result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
1311 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1312
1313 if (option_arg_vector_sp.get())
1314 {
1315 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1316
1317 for (size_t i = 0; i < option_arg_vector->size(); ++i)
1318 {
1319 OptionArgPair option_pair = (*option_arg_vector)[i];
1320 OptionArgValue value_pair = option_pair.second;
1321 int value_type = value_pair.first;
1322 std::string option = option_pair.first;
1323 std::string value = value_pair.second;
1324 if (option.compare ("<argument>") == 0)
1325 result_str.Printf (" %s", value.c_str());
1326 else
1327 {
1328 result_str.Printf (" %s", option.c_str());
1329 if (value_type != optional_argument)
1330 result_str.Printf (" ");
1331 if (value.compare ("<no_argument>") != 0)
1332 {
1333 int index = GetOptionArgumentPosition (value.c_str());
1334 if (index == 0)
1335 result_str.Printf ("%s", value.c_str());
1336 else if (index >= cmd_args.GetArgumentCount())
1337 {
1338
1339 result.AppendErrorWithFormat
1340 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
1341 index);
1342 result.SetStatus (eReturnStatusFailed);
1343 return alias_cmd_obj;
1344 }
1345 else
1346 {
1347 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
1348 if (strpos != std::string::npos)
1349 raw_input_string = raw_input_string.erase (strpos,
1350 strlen (cmd_args.GetArgumentAtIndex (index)));
1351 result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
1352 }
1353 }
1354 }
1355 }
1356 }
1357
1358 alias_result = result_str.GetData();
1359 }
1360 return alias_cmd_obj;
1361 }
1362
1363 Error
PreprocessCommand(std::string & command)1364 CommandInterpreter::PreprocessCommand (std::string &command)
1365 {
1366 // The command preprocessor needs to do things to the command
1367 // line before any parsing of arguments or anything else is done.
1368 // The only current stuff that gets proprocessed is anyting enclosed
1369 // in backtick ('`') characters is evaluated as an expression and
1370 // the result of the expression must be a scalar that can be substituted
1371 // into the command. An example would be:
1372 // (lldb) memory read `$rsp + 20`
1373 Error error; // Error for any expressions that might not evaluate
1374 size_t start_backtick;
1375 size_t pos = 0;
1376 while ((start_backtick = command.find ('`', pos)) != std::string::npos)
1377 {
1378 if (start_backtick > 0 && command[start_backtick-1] == '\\')
1379 {
1380 // The backtick was preceeded by a '\' character, remove the slash
1381 // and don't treat the backtick as the start of an expression
1382 command.erase(start_backtick-1, 1);
1383 // No need to add one to start_backtick since we just deleted a char
1384 pos = start_backtick;
1385 }
1386 else
1387 {
1388 const size_t expr_content_start = start_backtick + 1;
1389 const size_t end_backtick = command.find ('`', expr_content_start);
1390 if (end_backtick == std::string::npos)
1391 return error;
1392 else if (end_backtick == expr_content_start)
1393 {
1394 // Empty expression (two backticks in a row)
1395 command.erase (start_backtick, 2);
1396 }
1397 else
1398 {
1399 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
1400
1401 ExecutionContext exe_ctx(GetExecutionContext());
1402 Target *target = exe_ctx.GetTargetPtr();
1403 // Get a dummy target to allow for calculator mode while processing backticks.
1404 // This also helps break the infinite loop caused when target is null.
1405 if (!target)
1406 target = Host::GetDummyTarget(GetDebugger()).get();
1407 if (target)
1408 {
1409 ValueObjectSP expr_result_valobj_sp;
1410
1411 EvaluateExpressionOptions options;
1412 options.SetCoerceToId(false)
1413 .SetUnwindOnError(true)
1414 .SetIgnoreBreakpoints(true)
1415 .SetKeepInMemory(false)
1416 .SetRunOthers(true)
1417 .SetTimeoutUsec(0);
1418
1419 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
1420 exe_ctx.GetFramePtr(),
1421 expr_result_valobj_sp,
1422 options);
1423
1424 if (expr_result == eExecutionCompleted)
1425 {
1426 Scalar scalar;
1427 if (expr_result_valobj_sp->ResolveValue (scalar))
1428 {
1429 command.erase (start_backtick, end_backtick - start_backtick + 1);
1430 StreamString value_strm;
1431 const bool show_type = false;
1432 scalar.GetValue (&value_strm, show_type);
1433 size_t value_string_size = value_strm.GetSize();
1434 if (value_string_size)
1435 {
1436 command.insert (start_backtick, value_strm.GetData(), value_string_size);
1437 pos = start_backtick + value_string_size;
1438 continue;
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 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1448 }
1449 }
1450 else
1451 {
1452 if (expr_result_valobj_sp)
1453 error = expr_result_valobj_sp->GetError();
1454 if (error.Success())
1455 {
1456
1457 switch (expr_result)
1458 {
1459 case eExecutionSetupError:
1460 error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
1461 break;
1462 case eExecutionCompleted:
1463 break;
1464 case eExecutionDiscarded:
1465 error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
1466 break;
1467 case eExecutionInterrupted:
1468 error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
1469 break;
1470 case eExecutionHitBreakpoint:
1471 error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
1472 break;
1473 case eExecutionTimedOut:
1474 error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
1475 break;
1476 }
1477 }
1478 }
1479 }
1480 }
1481 if (error.Fail())
1482 break;
1483 }
1484 }
1485 return error;
1486 }
1487
1488
1489 bool
HandleCommand(const char * command_line,LazyBool lazy_add_to_history,CommandReturnObject & result,ExecutionContext * override_context,bool repeat_on_empty_command,bool no_context_switching)1490 CommandInterpreter::HandleCommand (const char *command_line,
1491 LazyBool lazy_add_to_history,
1492 CommandReturnObject &result,
1493 ExecutionContext *override_context,
1494 bool repeat_on_empty_command,
1495 bool no_context_switching)
1496
1497 {
1498
1499 bool done = false;
1500 CommandObject *cmd_obj = NULL;
1501 bool wants_raw_input = false;
1502 std::string command_string (command_line);
1503 std::string original_command_string (command_line);
1504
1505 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
1506 Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
1507
1508 // Make a scoped cleanup object that will clear the crash description string
1509 // on exit of this function.
1510 lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription);
1511
1512 if (log)
1513 log->Printf ("Processing command: %s", command_line);
1514
1515 Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
1516
1517 if (!no_context_switching)
1518 UpdateExecutionContext (override_context);
1519
1520 bool add_to_history;
1521 if (lazy_add_to_history == eLazyBoolCalculate)
1522 add_to_history = (m_command_source_depth == 0);
1523 else
1524 add_to_history = (lazy_add_to_history == eLazyBoolYes);
1525
1526 bool empty_command = false;
1527 bool comment_command = false;
1528 if (command_string.empty())
1529 empty_command = true;
1530 else
1531 {
1532 const char *k_space_characters = "\t\n\v\f\r ";
1533
1534 size_t non_space = command_string.find_first_not_of (k_space_characters);
1535 // Check for empty line or comment line (lines whose first
1536 // non-space character is the comment character for this interpreter)
1537 if (non_space == std::string::npos)
1538 empty_command = true;
1539 else if (command_string[non_space] == m_comment_char)
1540 comment_command = true;
1541 else if (command_string[non_space] == CommandHistory::g_repeat_char)
1542 {
1543 const char *history_string = m_command_history.FindString(command_string.c_str() + non_space);
1544 if (history_string == NULL)
1545 {
1546 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
1547 result.SetStatus(eReturnStatusFailed);
1548 return false;
1549 }
1550 add_to_history = false;
1551 command_string = history_string;
1552 original_command_string = history_string;
1553 }
1554 }
1555
1556 if (empty_command)
1557 {
1558 if (repeat_on_empty_command)
1559 {
1560 if (m_command_history.IsEmpty())
1561 {
1562 result.AppendError ("empty command");
1563 result.SetStatus(eReturnStatusFailed);
1564 return false;
1565 }
1566 else
1567 {
1568 command_line = m_repeat_command.c_str();
1569 command_string = command_line;
1570 original_command_string = command_line;
1571 if (m_repeat_command.empty())
1572 {
1573 result.AppendErrorWithFormat("No auto repeat.\n");
1574 result.SetStatus (eReturnStatusFailed);
1575 return false;
1576 }
1577 }
1578 add_to_history = false;
1579 }
1580 else
1581 {
1582 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1583 return true;
1584 }
1585 }
1586 else if (comment_command)
1587 {
1588 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1589 return true;
1590 }
1591
1592
1593 Error error (PreprocessCommand (command_string));
1594
1595 if (error.Fail())
1596 {
1597 result.AppendError (error.AsCString());
1598 result.SetStatus(eReturnStatusFailed);
1599 return false;
1600 }
1601 // Phase 1.
1602
1603 // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
1604 // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that
1605 // the user could have specified an alias, and in translating the alias there may also be command options and/or
1606 // even data (including raw text strings) that need to be found and inserted into the command line as part of
1607 // the translation. So this first step is plain look-up & replacement, resulting in three things: 1). the command
1608 // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
1609 // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
1610
1611 StreamString revised_command_line;
1612 size_t actual_cmd_name_len = 0;
1613 std::string next_word;
1614 StringList matches;
1615 while (!done)
1616 {
1617 char quote_char = '\0';
1618 std::string suffix;
1619 ExtractCommand (command_string, next_word, suffix, quote_char);
1620 if (cmd_obj == NULL)
1621 {
1622 std::string full_name;
1623 if (GetAliasFullName(next_word.c_str(), full_name))
1624 {
1625 std::string alias_result;
1626 cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result);
1627 revised_command_line.Printf ("%s", alias_result.c_str());
1628 if (cmd_obj)
1629 {
1630 wants_raw_input = cmd_obj->WantsRawCommandString ();
1631 actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
1632 }
1633 }
1634 else
1635 {
1636 cmd_obj = GetCommandObject (next_word.c_str(), &matches);
1637 if (cmd_obj)
1638 {
1639 actual_cmd_name_len += next_word.length();
1640 revised_command_line.Printf ("%s", next_word.c_str());
1641 wants_raw_input = cmd_obj->WantsRawCommandString ();
1642 }
1643 else
1644 {
1645 revised_command_line.Printf ("%s", next_word.c_str());
1646 }
1647 }
1648 }
1649 else
1650 {
1651 if (cmd_obj->IsMultiwordObject ())
1652 {
1653 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str());
1654 if (sub_cmd_obj)
1655 {
1656 actual_cmd_name_len += next_word.length() + 1;
1657 revised_command_line.Printf (" %s", next_word.c_str());
1658 cmd_obj = sub_cmd_obj;
1659 wants_raw_input = cmd_obj->WantsRawCommandString ();
1660 }
1661 else
1662 {
1663 if (quote_char)
1664 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1665 else
1666 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1667 done = true;
1668 }
1669 }
1670 else
1671 {
1672 if (quote_char)
1673 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1674 else
1675 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1676 done = true;
1677 }
1678 }
1679
1680 if (cmd_obj == NULL)
1681 {
1682 const size_t num_matches = matches.GetSize();
1683 if (matches.GetSize() > 1) {
1684 StreamString error_msg;
1685 error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());
1686
1687 for (uint32_t i = 0; i < num_matches; ++i) {
1688 error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i));
1689 }
1690 result.AppendRawError (error_msg.GetString().c_str());
1691 } else {
1692 // We didn't have only one match, otherwise we wouldn't get here.
1693 assert(num_matches == 0);
1694 result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
1695 }
1696 result.SetStatus (eReturnStatusFailed);
1697 return false;
1698 }
1699
1700 if (cmd_obj->IsMultiwordObject ())
1701 {
1702 if (!suffix.empty())
1703 {
1704
1705 result.AppendErrorWithFormat ("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n",
1706 cmd_obj->GetCommandName(),
1707 next_word.empty() ? "" : next_word.c_str(),
1708 next_word.empty() ? " -- " : " ",
1709 suffix.c_str());
1710 result.SetStatus (eReturnStatusFailed);
1711 return false;
1712 }
1713 }
1714 else
1715 {
1716 // If we found a normal command, we are done
1717 done = true;
1718 if (!suffix.empty())
1719 {
1720 switch (suffix[0])
1721 {
1722 case '/':
1723 // GDB format suffixes
1724 {
1725 Options *command_options = cmd_obj->GetOptions();
1726 if (command_options && command_options->SupportsLongOption("gdb-format"))
1727 {
1728 std::string gdb_format_option ("--gdb-format=");
1729 gdb_format_option += (suffix.c_str() + 1);
1730
1731 bool inserted = false;
1732 std::string &cmd = revised_command_line.GetString();
1733 size_t arg_terminator_idx = FindArgumentTerminator (cmd);
1734 if (arg_terminator_idx != std::string::npos)
1735 {
1736 // Insert the gdb format option before the "--" that terminates options
1737 gdb_format_option.append(1,' ');
1738 cmd.insert(arg_terminator_idx, gdb_format_option);
1739 inserted = true;
1740 }
1741
1742 if (!inserted)
1743 revised_command_line.Printf (" %s", gdb_format_option.c_str());
1744
1745 if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
1746 revised_command_line.PutCString (" --");
1747 }
1748 else
1749 {
1750 result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n",
1751 cmd_obj->GetCommandName());
1752 result.SetStatus (eReturnStatusFailed);
1753 return false;
1754 }
1755 }
1756 break;
1757
1758 default:
1759 result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n",
1760 suffix.c_str());
1761 result.SetStatus (eReturnStatusFailed);
1762 return false;
1763
1764 }
1765 }
1766 }
1767 if (command_string.length() == 0)
1768 done = true;
1769
1770 }
1771
1772 if (!command_string.empty())
1773 revised_command_line.Printf (" %s", command_string.c_str());
1774
1775 // End of Phase 1.
1776 // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
1777 // specified was valid; revised_command_line contains the complete command line (including command name(s)),
1778 // fully translated with all substitutions & translations taken care of (still in raw text format); and
1779 // wants_raw_input specifies whether the Execute method expects raw input or not.
1780
1781
1782 if (log)
1783 {
1784 log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
1785 log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
1786 log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
1787 }
1788
1789 // Phase 2.
1790 // Take care of things like setting up the history command & calling the appropriate Execute method on the
1791 // CommandObject, with the appropriate arguments.
1792
1793 if (cmd_obj != NULL)
1794 {
1795 if (add_to_history)
1796 {
1797 Args command_args (revised_command_line.GetData());
1798 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
1799 if (repeat_command != NULL)
1800 m_repeat_command.assign(repeat_command);
1801 else
1802 m_repeat_command.assign(original_command_string.c_str());
1803
1804 m_command_history.AppendString (original_command_string);
1805 }
1806
1807 command_string = revised_command_line.GetData();
1808 std::string command_name (cmd_obj->GetCommandName());
1809 std::string remainder;
1810 if (actual_cmd_name_len < command_string.length())
1811 remainder = command_string.substr (actual_cmd_name_len); // Note: 'actual_cmd_name_len' may be considerably shorter
1812 // than cmd_obj->GetCommandName(), because name completion
1813 // allows users to enter short versions of the names,
1814 // e.g. 'br s' for 'breakpoint set'.
1815
1816 // Remove any initial spaces
1817 std::string white_space (" \t\v");
1818 size_t pos = remainder.find_first_not_of (white_space);
1819 if (pos != 0 && pos != std::string::npos)
1820 remainder.erase(0, pos);
1821
1822 if (log)
1823 log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
1824
1825 cmd_obj->Execute (remainder.c_str(), result);
1826 }
1827 else
1828 {
1829 // We didn't find the first command object, so complete the first argument.
1830 Args command_args (revised_command_line.GetData());
1831 StringList matches;
1832 int num_matches;
1833 int cursor_index = 0;
1834 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
1835 bool word_complete;
1836 num_matches = HandleCompletionMatches (command_args,
1837 cursor_index,
1838 cursor_char_position,
1839 0,
1840 -1,
1841 word_complete,
1842 matches);
1843
1844 if (num_matches > 0)
1845 {
1846 std::string error_msg;
1847 error_msg.assign ("ambiguous command '");
1848 error_msg.append(command_args.GetArgumentAtIndex(0));
1849 error_msg.append ("'.");
1850
1851 error_msg.append (" Possible completions:");
1852 for (int i = 0; i < num_matches; i++)
1853 {
1854 error_msg.append ("\n\t");
1855 error_msg.append (matches.GetStringAtIndex (i));
1856 }
1857 error_msg.append ("\n");
1858 result.AppendRawError (error_msg.c_str());
1859 }
1860 else
1861 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
1862
1863 result.SetStatus (eReturnStatusFailed);
1864 }
1865
1866 if (log)
1867 log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
1868
1869 return result.Succeeded();
1870 }
1871
1872 int
HandleCompletionMatches(Args & parsed_line,int & cursor_index,int & cursor_char_position,int match_start_point,int max_return_elements,bool & word_complete,StringList & matches)1873 CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
1874 int &cursor_index,
1875 int &cursor_char_position,
1876 int match_start_point,
1877 int max_return_elements,
1878 bool &word_complete,
1879 StringList &matches)
1880 {
1881 int num_command_matches = 0;
1882 bool look_for_subcommand = false;
1883
1884 // For any of the command completions a unique match will be a complete word.
1885 word_complete = true;
1886
1887 if (cursor_index == -1)
1888 {
1889 // We got nothing on the command line, so return the list of commands
1890 bool include_aliases = true;
1891 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
1892 }
1893 else if (cursor_index == 0)
1894 {
1895 // The cursor is in the first argument, so just do a lookup in the dictionary.
1896 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
1897 num_command_matches = matches.GetSize();
1898
1899 if (num_command_matches == 1
1900 && cmd_obj && cmd_obj->IsMultiwordObject()
1901 && matches.GetStringAtIndex(0) != NULL
1902 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
1903 {
1904 look_for_subcommand = true;
1905 num_command_matches = 0;
1906 matches.DeleteStringAtIndex(0);
1907 parsed_line.AppendArgument ("");
1908 cursor_index++;
1909 cursor_char_position = 0;
1910 }
1911 }
1912
1913 if (cursor_index > 0 || look_for_subcommand)
1914 {
1915 // We are completing further on into a commands arguments, so find the command and tell it
1916 // to complete the command.
1917 // First see if there is a matching initial command:
1918 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
1919 if (command_object == NULL)
1920 {
1921 return 0;
1922 }
1923 else
1924 {
1925 parsed_line.Shift();
1926 cursor_index--;
1927 num_command_matches = command_object->HandleCompletion (parsed_line,
1928 cursor_index,
1929 cursor_char_position,
1930 match_start_point,
1931 max_return_elements,
1932 word_complete,
1933 matches);
1934 }
1935 }
1936
1937 return num_command_matches;
1938
1939 }
1940
1941 int
HandleCompletion(const char * current_line,const char * cursor,const char * last_char,int match_start_point,int max_return_elements,StringList & matches)1942 CommandInterpreter::HandleCompletion (const char *current_line,
1943 const char *cursor,
1944 const char *last_char,
1945 int match_start_point,
1946 int max_return_elements,
1947 StringList &matches)
1948 {
1949 // We parse the argument up to the cursor, so the last argument in parsed_line is
1950 // the one containing the cursor, and the cursor is after the last character.
1951
1952 Args parsed_line(current_line, last_char - current_line);
1953 Args partial_parsed_line(current_line, cursor - current_line);
1954
1955 // Don't complete comments, and if the line we are completing is just the history repeat character,
1956 // substitute the appropriate history line.
1957 const char *first_arg = parsed_line.GetArgumentAtIndex(0);
1958 if (first_arg)
1959 {
1960 if (first_arg[0] == m_comment_char)
1961 return 0;
1962 else if (first_arg[0] == CommandHistory::g_repeat_char)
1963 {
1964 const char *history_string = m_command_history.FindString (first_arg);
1965 if (history_string != NULL)
1966 {
1967 matches.Clear();
1968 matches.InsertStringAtIndex(0, history_string);
1969 return -2;
1970 }
1971 else
1972 return 0;
1973
1974 }
1975 }
1976
1977
1978 int num_args = partial_parsed_line.GetArgumentCount();
1979 int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
1980 int cursor_char_position;
1981
1982 if (cursor_index == -1)
1983 cursor_char_position = 0;
1984 else
1985 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
1986
1987 if (cursor > current_line && cursor[-1] == ' ')
1988 {
1989 // We are just after a space. If we are in an argument, then we will continue
1990 // parsing, but if we are between arguments, then we have to complete whatever the next
1991 // element would be.
1992 // We can distinguish the two cases because if we are in an argument (e.g. because the space is
1993 // protected by a quote) then the space will also be in the parsed argument...
1994
1995 const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
1996 if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
1997 {
1998 parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '"');
1999 cursor_index++;
2000 cursor_char_position = 0;
2001 }
2002 }
2003
2004 int num_command_matches;
2005
2006 matches.Clear();
2007
2008 // Only max_return_elements == -1 is supported at present:
2009 assert (max_return_elements == -1);
2010 bool word_complete;
2011 num_command_matches = HandleCompletionMatches (parsed_line,
2012 cursor_index,
2013 cursor_char_position,
2014 match_start_point,
2015 max_return_elements,
2016 word_complete,
2017 matches);
2018
2019 if (num_command_matches <= 0)
2020 return num_command_matches;
2021
2022 if (num_args == 0)
2023 {
2024 // If we got an empty string, insert nothing.
2025 matches.InsertStringAtIndex(0, "");
2026 }
2027 else
2028 {
2029 // Now figure out if there is a common substring, and if so put that in element 0, otherwise
2030 // put an empty string in element 0.
2031 std::string command_partial_str;
2032 if (cursor_index >= 0)
2033 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
2034 parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
2035
2036 std::string common_prefix;
2037 matches.LongestCommonPrefix (common_prefix);
2038 const size_t partial_name_len = command_partial_str.size();
2039
2040 // If we matched a unique single command, add a space...
2041 // Only do this if the completer told us this was a complete word, however...
2042 if (num_command_matches == 1 && word_complete)
2043 {
2044 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
2045 if (quote_char != '\0')
2046 common_prefix.push_back(quote_char);
2047
2048 common_prefix.push_back(' ');
2049 }
2050 common_prefix.erase (0, partial_name_len);
2051 matches.InsertStringAtIndex(0, common_prefix.c_str());
2052 }
2053 return num_command_matches;
2054 }
2055
2056
~CommandInterpreter()2057 CommandInterpreter::~CommandInterpreter ()
2058 {
2059 }
2060
2061 const char *
GetPrompt()2062 CommandInterpreter::GetPrompt ()
2063 {
2064 return m_debugger.GetPrompt();
2065 }
2066
2067 void
SetPrompt(const char * new_prompt)2068 CommandInterpreter::SetPrompt (const char *new_prompt)
2069 {
2070 m_debugger.SetPrompt (new_prompt);
2071 }
2072
2073 size_t
GetConfirmationInputReaderCallback(void * baton,InputReader & reader,lldb::InputReaderAction action,const char * bytes,size_t bytes_len)2074 CommandInterpreter::GetConfirmationInputReaderCallback
2075 (
2076 void *baton,
2077 InputReader &reader,
2078 lldb::InputReaderAction action,
2079 const char *bytes,
2080 size_t bytes_len
2081 )
2082 {
2083 File &out_file = reader.GetDebugger().GetOutputFile();
2084 bool *response_ptr = (bool *) baton;
2085
2086 switch (action)
2087 {
2088 case eInputReaderActivate:
2089 if (out_file.IsValid())
2090 {
2091 if (reader.GetPrompt())
2092 {
2093 out_file.Printf ("%s", reader.GetPrompt());
2094 out_file.Flush ();
2095 }
2096 }
2097 break;
2098
2099 case eInputReaderDeactivate:
2100 break;
2101
2102 case eInputReaderReactivate:
2103 if (out_file.IsValid() && reader.GetPrompt())
2104 {
2105 out_file.Printf ("%s", reader.GetPrompt());
2106 out_file.Flush ();
2107 }
2108 break;
2109
2110 case eInputReaderAsynchronousOutputWritten:
2111 break;
2112
2113 case eInputReaderGotToken:
2114 if (bytes_len == 0)
2115 {
2116 reader.SetIsDone(true);
2117 }
2118 else if (bytes[0] == 'y' || bytes[0] == 'Y')
2119 {
2120 *response_ptr = true;
2121 reader.SetIsDone(true);
2122 }
2123 else if (bytes[0] == 'n' || bytes[0] == 'N')
2124 {
2125 *response_ptr = false;
2126 reader.SetIsDone(true);
2127 }
2128 else
2129 {
2130 if (out_file.IsValid() && !reader.IsDone() && reader.GetPrompt())
2131 {
2132 out_file.Printf ("Please answer \"y\" or \"n\".\n%s", reader.GetPrompt());
2133 out_file.Flush ();
2134 }
2135 }
2136 break;
2137
2138 case eInputReaderInterrupt:
2139 case eInputReaderEndOfFile:
2140 *response_ptr = false; // Assume ^C or ^D means cancel the proposed action
2141 reader.SetIsDone (true);
2142 break;
2143
2144 case eInputReaderDone:
2145 break;
2146 }
2147
2148 return bytes_len;
2149
2150 }
2151
2152 bool
Confirm(const char * message,bool default_answer)2153 CommandInterpreter::Confirm (const char *message, bool default_answer)
2154 {
2155 // Check AutoConfirm first:
2156 if (m_debugger.GetAutoConfirm())
2157 return default_answer;
2158
2159 InputReaderSP reader_sp (new InputReader(GetDebugger()));
2160 bool response = default_answer;
2161 if (reader_sp)
2162 {
2163 std::string prompt(message);
2164 prompt.append(": [");
2165 if (default_answer)
2166 prompt.append ("Y/n] ");
2167 else
2168 prompt.append ("y/N] ");
2169
2170 Error err (reader_sp->Initialize (CommandInterpreter::GetConfirmationInputReaderCallback,
2171 &response, // baton
2172 eInputReaderGranularityLine, // token size, to pass to callback function
2173 NULL, // end token
2174 prompt.c_str(), // prompt
2175 true)); // echo input
2176 if (err.Success())
2177 {
2178 GetDebugger().PushInputReader (reader_sp);
2179 }
2180 reader_sp->WaitOnReaderIsDone();
2181 }
2182 return response;
2183 }
2184
2185 OptionArgVectorSP
GetAliasOptions(const char * alias_name)2186 CommandInterpreter::GetAliasOptions (const char *alias_name)
2187 {
2188 OptionArgMap::iterator pos;
2189 OptionArgVectorSP ret_val;
2190
2191 std::string alias (alias_name);
2192
2193 if (HasAliasOptions())
2194 {
2195 pos = m_alias_options.find (alias);
2196 if (pos != m_alias_options.end())
2197 ret_val = pos->second;
2198 }
2199
2200 return ret_val;
2201 }
2202
2203 void
RemoveAliasOptions(const char * alias_name)2204 CommandInterpreter::RemoveAliasOptions (const char *alias_name)
2205 {
2206 OptionArgMap::iterator pos = m_alias_options.find(alias_name);
2207 if (pos != m_alias_options.end())
2208 {
2209 m_alias_options.erase (pos);
2210 }
2211 }
2212
2213 void
AddOrReplaceAliasOptions(const char * alias_name,OptionArgVectorSP & option_arg_vector_sp)2214 CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
2215 {
2216 m_alias_options[alias_name] = option_arg_vector_sp;
2217 }
2218
2219 bool
HasCommands()2220 CommandInterpreter::HasCommands ()
2221 {
2222 return (!m_command_dict.empty());
2223 }
2224
2225 bool
HasAliases()2226 CommandInterpreter::HasAliases ()
2227 {
2228 return (!m_alias_dict.empty());
2229 }
2230
2231 bool
HasUserCommands()2232 CommandInterpreter::HasUserCommands ()
2233 {
2234 return (!m_user_dict.empty());
2235 }
2236
2237 bool
HasAliasOptions()2238 CommandInterpreter::HasAliasOptions ()
2239 {
2240 return (!m_alias_options.empty());
2241 }
2242
2243 void
BuildAliasCommandArgs(CommandObject * alias_cmd_obj,const char * alias_name,Args & cmd_args,std::string & raw_input_string,CommandReturnObject & result)2244 CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
2245 const char *alias_name,
2246 Args &cmd_args,
2247 std::string &raw_input_string,
2248 CommandReturnObject &result)
2249 {
2250 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
2251
2252 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
2253
2254 // Make sure that the alias name is the 0th element in cmd_args
2255 std::string alias_name_str = alias_name;
2256 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
2257 cmd_args.Unshift (alias_name);
2258
2259 Args new_args (alias_cmd_obj->GetCommandName());
2260 if (new_args.GetArgumentCount() == 2)
2261 new_args.Shift();
2262
2263 if (option_arg_vector_sp.get())
2264 {
2265 if (wants_raw_input)
2266 {
2267 // We have a command that both has command options and takes raw input. Make *sure* it has a
2268 // " -- " in the right place in the raw_input_string.
2269 size_t pos = raw_input_string.find(" -- ");
2270 if (pos == std::string::npos)
2271 {
2272 // None found; assume it goes at the beginning of the raw input string
2273 raw_input_string.insert (0, " -- ");
2274 }
2275 }
2276
2277 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
2278 const size_t old_size = cmd_args.GetArgumentCount();
2279 std::vector<bool> used (old_size + 1, false);
2280
2281 used[0] = true;
2282
2283 for (size_t i = 0; i < option_arg_vector->size(); ++i)
2284 {
2285 OptionArgPair option_pair = (*option_arg_vector)[i];
2286 OptionArgValue value_pair = option_pair.second;
2287 int value_type = value_pair.first;
2288 std::string option = option_pair.first;
2289 std::string value = value_pair.second;
2290 if (option.compare ("<argument>") == 0)
2291 {
2292 if (!wants_raw_input
2293 || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
2294 new_args.AppendArgument (value.c_str());
2295 }
2296 else
2297 {
2298 if (value_type != optional_argument)
2299 new_args.AppendArgument (option.c_str());
2300 if (value.compare ("<no-argument>") != 0)
2301 {
2302 int index = GetOptionArgumentPosition (value.c_str());
2303 if (index == 0)
2304 {
2305 // value was NOT a positional argument; must be a real value
2306 if (value_type != optional_argument)
2307 new_args.AppendArgument (value.c_str());
2308 else
2309 {
2310 char buffer[255];
2311 ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
2312 new_args.AppendArgument (buffer);
2313 }
2314
2315 }
2316 else if (index >= cmd_args.GetArgumentCount())
2317 {
2318 result.AppendErrorWithFormat
2319 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
2320 index);
2321 result.SetStatus (eReturnStatusFailed);
2322 return;
2323 }
2324 else
2325 {
2326 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2327 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
2328 if (strpos != std::string::npos)
2329 {
2330 raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
2331 }
2332
2333 if (value_type != optional_argument)
2334 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
2335 else
2336 {
2337 char buffer[255];
2338 ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
2339 cmd_args.GetArgumentAtIndex (index));
2340 new_args.AppendArgument (buffer);
2341 }
2342 used[index] = true;
2343 }
2344 }
2345 }
2346 }
2347
2348 for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j)
2349 {
2350 if (!used[j] && !wants_raw_input)
2351 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
2352 }
2353
2354 cmd_args.Clear();
2355 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2356 }
2357 else
2358 {
2359 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2360 // This alias was not created with any options; nothing further needs to be done, unless it is a command that
2361 // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
2362 // input string.
2363 if (wants_raw_input)
2364 {
2365 cmd_args.Clear();
2366 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2367 }
2368 return;
2369 }
2370
2371 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2372 return;
2373 }
2374
2375
2376 int
GetOptionArgumentPosition(const char * in_string)2377 CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
2378 {
2379 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
2380 // of zero.
2381
2382 char *cptr = (char *) in_string;
2383
2384 // Does it start with '%'
2385 if (cptr[0] == '%')
2386 {
2387 ++cptr;
2388
2389 // Is the rest of it entirely digits?
2390 if (isdigit (cptr[0]))
2391 {
2392 const char *start = cptr;
2393 while (isdigit (cptr[0]))
2394 ++cptr;
2395
2396 // We've gotten to the end of the digits; are we at the end of the string?
2397 if (cptr[0] == '\0')
2398 position = atoi (start);
2399 }
2400 }
2401
2402 return position;
2403 }
2404
2405 void
SourceInitFile(bool in_cwd,CommandReturnObject & result)2406 CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
2407 {
2408 FileSpec init_file;
2409 if (in_cwd)
2410 {
2411 // In the current working directory we don't load any program specific
2412 // .lldbinit files, we only look for a "./.lldbinit" file.
2413 if (m_skip_lldbinit_files)
2414 return;
2415
2416 init_file.SetFile ("./.lldbinit", true);
2417 }
2418 else
2419 {
2420 // If we aren't looking in the current working directory we are looking
2421 // in the home directory. We will first see if there is an application
2422 // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
2423 // "-" and the name of the program. If this file doesn't exist, we fall
2424 // back to just the "~/.lldbinit" file. We also obey any requests to not
2425 // load the init files.
2426 const char *init_file_path = "~/.lldbinit";
2427
2428 if (m_skip_app_init_files == false)
2429 {
2430 FileSpec program_file_spec (Host::GetProgramFileSpec());
2431 const char *program_name = program_file_spec.GetFilename().AsCString();
2432
2433 if (program_name)
2434 {
2435 char program_init_file_name[PATH_MAX];
2436 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name);
2437 init_file.SetFile (program_init_file_name, true);
2438 if (!init_file.Exists())
2439 init_file.Clear();
2440 }
2441 }
2442
2443 if (!init_file && !m_skip_lldbinit_files)
2444 init_file.SetFile (init_file_path, true);
2445 }
2446
2447 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
2448 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
2449
2450 if (init_file.Exists())
2451 {
2452 ExecutionContext *exe_ctx = NULL; // We don't have any context yet.
2453 bool stop_on_continue = true;
2454 bool stop_on_error = false;
2455 bool echo_commands = false;
2456 bool print_results = false;
2457
2458 HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, eLazyBoolNo, result);
2459 }
2460 else
2461 {
2462 // nothing to be done if the file doesn't exist
2463 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2464 }
2465 }
2466
2467 PlatformSP
GetPlatform(bool prefer_target_platform)2468 CommandInterpreter::GetPlatform (bool prefer_target_platform)
2469 {
2470 PlatformSP platform_sp;
2471 if (prefer_target_platform)
2472 {
2473 ExecutionContext exe_ctx(GetExecutionContext());
2474 Target *target = exe_ctx.GetTargetPtr();
2475 if (target)
2476 platform_sp = target->GetPlatform();
2477 }
2478
2479 if (!platform_sp)
2480 platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
2481 return platform_sp;
2482 }
2483
2484 void
HandleCommands(const StringList & commands,ExecutionContext * override_context,bool stop_on_continue,bool stop_on_error,bool echo_commands,bool print_results,LazyBool add_to_history,CommandReturnObject & result)2485 CommandInterpreter::HandleCommands (const StringList &commands,
2486 ExecutionContext *override_context,
2487 bool stop_on_continue,
2488 bool stop_on_error,
2489 bool echo_commands,
2490 bool print_results,
2491 LazyBool add_to_history,
2492 CommandReturnObject &result)
2493 {
2494 size_t num_lines = commands.GetSize();
2495
2496 // If we are going to continue past a "continue" then we need to run the commands synchronously.
2497 // Make sure you reset this value anywhere you return from the function.
2498
2499 bool old_async_execution = m_debugger.GetAsyncExecution();
2500
2501 // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
2502 // cause series of commands that change the context, then do an operation that relies on that context to fail.
2503
2504 if (override_context != NULL)
2505 UpdateExecutionContext (override_context);
2506
2507 if (!stop_on_continue)
2508 {
2509 m_debugger.SetAsyncExecution (false);
2510 }
2511
2512 for (size_t idx = 0; idx < num_lines; idx++)
2513 {
2514 const char *cmd = commands.GetStringAtIndex(idx);
2515 if (cmd[0] == '\0')
2516 continue;
2517
2518 if (echo_commands)
2519 {
2520 result.AppendMessageWithFormat ("%s %s\n",
2521 GetPrompt(),
2522 cmd);
2523 }
2524
2525 CommandReturnObject tmp_result;
2526 // If override_context is not NULL, pass no_context_switching = true for
2527 // HandleCommand() since we updated our context already.
2528
2529 // We might call into a regex or alias command, in which case the add_to_history will get lost. This
2530 // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
2531 if (!add_to_history)
2532 m_command_source_depth++;
2533 bool success = HandleCommand(cmd, add_to_history, tmp_result,
2534 NULL, /* override_context */
2535 true, /* repeat_on_empty_command */
2536 override_context != NULL /* no_context_switching */);
2537 if (!add_to_history)
2538 m_command_source_depth--;
2539
2540 if (print_results)
2541 {
2542 if (tmp_result.Succeeded())
2543 result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
2544 }
2545
2546 if (!success || !tmp_result.Succeeded())
2547 {
2548 const char *error_msg = tmp_result.GetErrorData();
2549 if (error_msg == NULL || error_msg[0] == '\0')
2550 error_msg = "<unknown error>.\n";
2551 if (stop_on_error)
2552 {
2553 result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' failed with %s",
2554 idx, cmd, error_msg);
2555 result.SetStatus (eReturnStatusFailed);
2556 m_debugger.SetAsyncExecution (old_async_execution);
2557 return;
2558 }
2559 else if (print_results)
2560 {
2561 result.AppendMessageWithFormat ("Command #%zu '%s' failed with %s",
2562 idx + 1,
2563 cmd,
2564 error_msg);
2565 }
2566 }
2567
2568 if (result.GetImmediateOutputStream())
2569 result.GetImmediateOutputStream()->Flush();
2570
2571 if (result.GetImmediateErrorStream())
2572 result.GetImmediateErrorStream()->Flush();
2573
2574 // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
2575 // could be running (for instance in Breakpoint Commands.
2576 // So we check the return value to see if it is has running in it.
2577 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
2578 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
2579 {
2580 if (stop_on_continue)
2581 {
2582 // If we caused the target to proceed, and we're going to stop in that case, set the
2583 // status in our real result before returning. This is an error if the continue was not the
2584 // last command in the set of commands to be run.
2585 if (idx != num_lines - 1)
2586 result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' continued the target.\n",
2587 idx + 1, cmd);
2588 else
2589 result.AppendMessageWithFormat ("Command #%zu '%s' continued the target.\n", idx + 1, cmd);
2590
2591 result.SetStatus(tmp_result.GetStatus());
2592 m_debugger.SetAsyncExecution (old_async_execution);
2593
2594 return;
2595 }
2596 }
2597
2598 }
2599
2600 result.SetStatus (eReturnStatusSuccessFinishResult);
2601 m_debugger.SetAsyncExecution (old_async_execution);
2602
2603 return;
2604 }
2605
2606 void
HandleCommandsFromFile(FileSpec & cmd_file,ExecutionContext * context,bool stop_on_continue,bool stop_on_error,bool echo_command,bool print_result,LazyBool add_to_history,CommandReturnObject & result)2607 CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
2608 ExecutionContext *context,
2609 bool stop_on_continue,
2610 bool stop_on_error,
2611 bool echo_command,
2612 bool print_result,
2613 LazyBool add_to_history,
2614 CommandReturnObject &result)
2615 {
2616 if (cmd_file.Exists())
2617 {
2618 bool success;
2619 StringList commands;
2620 success = commands.ReadFileLines(cmd_file);
2621 if (!success)
2622 {
2623 result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString());
2624 result.SetStatus (eReturnStatusFailed);
2625 return;
2626 }
2627 m_command_source_depth++;
2628 HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, add_to_history, result);
2629 m_command_source_depth--;
2630 }
2631 else
2632 {
2633 result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
2634 cmd_file.GetFilename().AsCString());
2635 result.SetStatus (eReturnStatusFailed);
2636 return;
2637 }
2638 }
2639
2640 ScriptInterpreter *
GetScriptInterpreter(bool can_create)2641 CommandInterpreter::GetScriptInterpreter (bool can_create)
2642 {
2643 if (m_script_interpreter_ap.get() != NULL)
2644 return m_script_interpreter_ap.get();
2645
2646 if (!can_create)
2647 return NULL;
2648
2649 // <rdar://problem/11751427>
2650 // we need to protect the initialization of the script interpreter
2651 // otherwise we could end up with two threads both trying to create
2652 // their instance of it, and for some languages (e.g. Python)
2653 // this is a bulletproof recipe for disaster!
2654 // this needs to be a function-level static because multiple Debugger instances living in the same process
2655 // still need to be isolated and not try to initialize Python concurrently
2656 static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
2657 Mutex::Locker interpreter_lock(g_interpreter_mutex);
2658
2659 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
2660 if (log)
2661 log->Printf("Initializing the ScriptInterpreter now\n");
2662
2663 lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
2664 switch (script_lang)
2665 {
2666 case eScriptLanguagePython:
2667 #ifndef LLDB_DISABLE_PYTHON
2668 m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
2669 break;
2670 #else
2671 // Fall through to the None case when python is disabled
2672 #endif
2673 case eScriptLanguageNone:
2674 m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
2675 break;
2676 };
2677
2678 return m_script_interpreter_ap.get();
2679 }
2680
2681
2682
2683 bool
GetSynchronous()2684 CommandInterpreter::GetSynchronous ()
2685 {
2686 return m_synchronous_execution;
2687 }
2688
2689 void
SetSynchronous(bool value)2690 CommandInterpreter::SetSynchronous (bool value)
2691 {
2692 m_synchronous_execution = value;
2693 }
2694
2695 void
OutputFormattedHelpText(Stream & strm,const char * word_text,const char * separator,const char * help_text,size_t max_word_len)2696 CommandInterpreter::OutputFormattedHelpText (Stream &strm,
2697 const char *word_text,
2698 const char *separator,
2699 const char *help_text,
2700 size_t max_word_len)
2701 {
2702 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2703
2704 int indent_size = max_word_len + strlen (separator) + 2;
2705
2706 strm.IndentMore (indent_size);
2707
2708 StreamString text_strm;
2709 text_strm.Printf ("%-*s %s %s", (int)max_word_len, word_text, separator, help_text);
2710
2711 size_t len = text_strm.GetSize();
2712 const char *text = text_strm.GetData();
2713 if (text[len - 1] == '\n')
2714 {
2715 text_strm.EOL();
2716 len = text_strm.GetSize();
2717 }
2718
2719 if (len < max_columns)
2720 {
2721 // Output it as a single line.
2722 strm.Printf ("%s", text);
2723 }
2724 else
2725 {
2726 // We need to break it up into multiple lines.
2727 bool first_line = true;
2728 int text_width;
2729 size_t start = 0;
2730 size_t end = start;
2731 const size_t final_end = strlen (text);
2732
2733 while (end < final_end)
2734 {
2735 if (first_line)
2736 text_width = max_columns - 1;
2737 else
2738 text_width = max_columns - indent_size - 1;
2739
2740 // Don't start the 'text' on a space, since we're already outputting the indentation.
2741 if (!first_line)
2742 {
2743 while ((start < final_end) && (text[start] == ' '))
2744 start++;
2745 }
2746
2747 end = start + text_width;
2748 if (end > final_end)
2749 end = final_end;
2750 else
2751 {
2752 // If we're not at the end of the text, make sure we break the line on white space.
2753 while (end > start
2754 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
2755 end--;
2756 assert (end > 0);
2757 }
2758
2759 const size_t sub_len = end - start;
2760 if (start != 0)
2761 strm.EOL();
2762 if (!first_line)
2763 strm.Indent();
2764 else
2765 first_line = false;
2766 assert (start <= final_end);
2767 assert (start + sub_len <= final_end);
2768 if (sub_len > 0)
2769 strm.Write (text + start, sub_len);
2770 start = end + 1;
2771 }
2772 }
2773 strm.EOL();
2774 strm.IndentLess(indent_size);
2775 }
2776
2777 void
OutputHelpText(Stream & strm,const char * word_text,const char * separator,const char * help_text,uint32_t max_word_len)2778 CommandInterpreter::OutputHelpText (Stream &strm,
2779 const char *word_text,
2780 const char *separator,
2781 const char *help_text,
2782 uint32_t max_word_len)
2783 {
2784 int indent_size = max_word_len + strlen (separator) + 2;
2785
2786 strm.IndentMore (indent_size);
2787
2788 StreamString text_strm;
2789 text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
2790
2791 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2792
2793 size_t len = text_strm.GetSize();
2794 const char *text = text_strm.GetData();
2795
2796 uint32_t chars_left = max_columns;
2797
2798 for (uint32_t i = 0; i < len; i++)
2799 {
2800 if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
2801 {
2802 chars_left = max_columns - indent_size;
2803 strm.EOL();
2804 strm.Indent();
2805 }
2806 else
2807 {
2808 strm.PutChar(text[i]);
2809 chars_left--;
2810 }
2811
2812 }
2813
2814 strm.EOL();
2815 strm.IndentLess(indent_size);
2816 }
2817
2818 void
FindCommandsForApropos(const char * search_word,StringList & commands_found,StringList & commands_help,bool search_builtin_commands,bool search_user_commands)2819 CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
2820 StringList &commands_help, bool search_builtin_commands, bool search_user_commands)
2821 {
2822 CommandObject::CommandMap::const_iterator pos;
2823
2824 if (search_builtin_commands)
2825 {
2826 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
2827 {
2828 const char *command_name = pos->first.c_str();
2829 CommandObject *cmd_obj = pos->second.get();
2830
2831 if (cmd_obj->HelpTextContainsWord (search_word))
2832 {
2833 commands_found.AppendString (command_name);
2834 commands_help.AppendString (cmd_obj->GetHelp());
2835 }
2836
2837 if (cmd_obj->IsMultiwordObject())
2838 cmd_obj->AproposAllSubCommands (command_name,
2839 search_word,
2840 commands_found,
2841 commands_help);
2842
2843 }
2844 }
2845
2846 if (search_user_commands)
2847 {
2848 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
2849 {
2850 const char *command_name = pos->first.c_str();
2851 CommandObject *cmd_obj = pos->second.get();
2852
2853 if (cmd_obj->HelpTextContainsWord (search_word))
2854 {
2855 commands_found.AppendString (command_name);
2856 commands_help.AppendString (cmd_obj->GetHelp());
2857 }
2858
2859 if (cmd_obj->IsMultiwordObject())
2860 cmd_obj->AproposAllSubCommands (command_name,
2861 search_word,
2862 commands_found,
2863 commands_help);
2864
2865 }
2866 }
2867 }
2868
2869
2870 void
UpdateExecutionContext(ExecutionContext * override_context)2871 CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
2872 {
2873 if (override_context != NULL)
2874 {
2875 m_exe_ctx_ref = *override_context;
2876 }
2877 else
2878 {
2879 const bool adopt_selected = true;
2880 m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
2881 }
2882 }
2883