1 //===-- CommandObjectSource.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 "CommandObjectCommands.h"
13
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 #include "llvm/ADT/StringRef.h"
18
19 // Project includes
20 #include "lldb/Core/Debugger.h"
21 #include "lldb/Core/InputReader.h"
22 #include "lldb/Core/InputReaderEZ.h"
23 #include "lldb/Core/StringList.h"
24 #include "lldb/Interpreter/Args.h"
25 #include "lldb/Interpreter/CommandHistory.h"
26 #include "lldb/Interpreter/CommandInterpreter.h"
27 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
28 #include "lldb/Interpreter/CommandReturnObject.h"
29 #include "lldb/Interpreter/OptionValueBoolean.h"
30 #include "lldb/Interpreter/OptionValueUInt64.h"
31 #include "lldb/Interpreter/Options.h"
32 #include "lldb/Interpreter/ScriptInterpreter.h"
33 #include "lldb/Interpreter/ScriptInterpreterPython.h"
34
35 using namespace lldb;
36 using namespace lldb_private;
37
38 //-------------------------------------------------------------------------
39 // CommandObjectCommandsSource
40 //-------------------------------------------------------------------------
41
42 class CommandObjectCommandsHistory : public CommandObjectParsed
43 {
44 public:
CommandObjectCommandsHistory(CommandInterpreter & interpreter)45 CommandObjectCommandsHistory(CommandInterpreter &interpreter) :
46 CommandObjectParsed (interpreter,
47 "command history",
48 "Dump the history of commands in this session.",
49 NULL),
50 m_options (interpreter)
51 {
52 }
53
~CommandObjectCommandsHistory()54 ~CommandObjectCommandsHistory () {}
55
56 virtual Options *
GetOptions()57 GetOptions ()
58 {
59 return &m_options;
60 }
61
62 protected:
63
64 class CommandOptions : public Options
65 {
66 public:
67
CommandOptions(CommandInterpreter & interpreter)68 CommandOptions (CommandInterpreter &interpreter) :
69 Options (interpreter),
70 m_start_idx(0),
71 m_stop_idx(0),
72 m_count(0),
73 m_clear(false)
74 {
75 }
76
77 virtual
~CommandOptions()78 ~CommandOptions (){}
79
80 virtual Error
SetOptionValue(uint32_t option_idx,const char * option_arg)81 SetOptionValue (uint32_t option_idx, const char *option_arg)
82 {
83 Error error;
84 const int short_option = m_getopt_table[option_idx].val;
85
86 switch (short_option)
87 {
88 case 'c':
89 error = m_count.SetValueFromCString(option_arg,eVarSetOperationAssign);
90 break;
91 case 's':
92 if (option_arg && strcmp("end", option_arg) == 0)
93 {
94 m_start_idx.SetCurrentValue(UINT64_MAX);
95 m_start_idx.SetOptionWasSet();
96 }
97 else
98 error = m_start_idx.SetValueFromCString(option_arg,eVarSetOperationAssign);
99 break;
100 case 'e':
101 error = m_stop_idx.SetValueFromCString(option_arg,eVarSetOperationAssign);
102 break;
103 case 'C':
104 m_clear.SetCurrentValue(true);
105 m_clear.SetOptionWasSet();
106 break;
107 default:
108 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
109 break;
110 }
111
112 return error;
113 }
114
115 void
OptionParsingStarting()116 OptionParsingStarting ()
117 {
118 m_start_idx.Clear();
119 m_stop_idx.Clear();
120 m_count.Clear();
121 m_clear.Clear();
122 }
123
124 const OptionDefinition*
GetDefinitions()125 GetDefinitions ()
126 {
127 return g_option_table;
128 }
129
130 // Options table: Required for subclasses of Options.
131
132 static OptionDefinition g_option_table[];
133
134 // Instance variables to hold the values for command options.
135
136 OptionValueUInt64 m_start_idx;
137 OptionValueUInt64 m_stop_idx;
138 OptionValueUInt64 m_count;
139 OptionValueBoolean m_clear;
140 };
141
142 bool
DoExecute(Args & command,CommandReturnObject & result)143 DoExecute (Args& command, CommandReturnObject &result)
144 {
145 if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet())
146 {
147 m_interpreter.GetCommandHistory().Clear();
148 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
149 }
150 else
151 {
152 if (m_options.m_start_idx.OptionWasSet() && m_options.m_stop_idx.OptionWasSet() && m_options.m_count.OptionWasSet())
153 {
154 result.AppendError("--count, --start-index and --end-index cannot be all specified in the same invocation");
155 result.SetStatus(lldb::eReturnStatusFailed);
156 }
157 else
158 {
159 std::pair<bool,uint64_t> start_idx = {m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue()};
160 std::pair<bool,uint64_t> stop_idx = {m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue()};
161 std::pair<bool,uint64_t> count = {m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue()};
162
163 const CommandHistory& history(m_interpreter.GetCommandHistory());
164
165 if (start_idx.first && start_idx.second == UINT64_MAX)
166 {
167 if (count.first)
168 {
169 start_idx.second = history.GetSize() - count.second;
170 stop_idx.second = history.GetSize() - 1;
171 }
172 else if (stop_idx.first)
173 {
174 start_idx.second = stop_idx.second;
175 stop_idx.second = history.GetSize() - 1;
176 }
177 else
178 {
179 start_idx.second = 0;
180 stop_idx.second = history.GetSize() - 1;
181 }
182 }
183 else
184 {
185 if (!start_idx.first && !stop_idx.first && !count.first)
186 {
187 start_idx.second = 0;
188 stop_idx.second = history.GetSize() - 1;
189 }
190 else if (start_idx.first)
191 {
192 if (count.first)
193 {
194 stop_idx.second = start_idx.second + count.second - 1;
195 }
196 else if (!stop_idx.first)
197 {
198 stop_idx.second = history.GetSize() - 1;
199 }
200 }
201 else if (stop_idx.first)
202 {
203 if (count.first)
204 {
205 if (stop_idx.second >= count.second)
206 start_idx.second = stop_idx.second - count.second + 1;
207 else
208 start_idx.second = 0;
209 }
210 }
211 else /* if (count.first) */
212 {
213 start_idx.second = 0;
214 stop_idx.second = count.second - 1;
215 }
216 }
217 history.Dump(result.GetOutputStream(), start_idx.second, stop_idx.second);
218 }
219 }
220 return result.Succeeded();
221
222 }
223
224 CommandOptions m_options;
225 };
226
227 OptionDefinition
228 CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
229 {
230 { LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
231 { LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)."},
232 { LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
233 { LLDB_OPT_SET_2, false, "clear", 'C', no_argument, NULL, 0, eArgTypeBoolean, "Clears the current command history."},
234 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
235 };
236
237
238 //-------------------------------------------------------------------------
239 // CommandObjectCommandsSource
240 //-------------------------------------------------------------------------
241
242 class CommandObjectCommandsSource : public CommandObjectParsed
243 {
244 public:
CommandObjectCommandsSource(CommandInterpreter & interpreter)245 CommandObjectCommandsSource(CommandInterpreter &interpreter) :
246 CommandObjectParsed (interpreter,
247 "command source",
248 "Read in debugger commands from the file <filename> and execute them.",
249 NULL),
250 m_options (interpreter)
251 {
252 CommandArgumentEntry arg;
253 CommandArgumentData file_arg;
254
255 // Define the first (and only) variant of this arg.
256 file_arg.arg_type = eArgTypeFilename;
257 file_arg.arg_repetition = eArgRepeatPlain;
258
259 // There is only one variant this argument could be; put it into the argument entry.
260 arg.push_back (file_arg);
261
262 // Push the data for the first argument into the m_arguments vector.
263 m_arguments.push_back (arg);
264 }
265
~CommandObjectCommandsSource()266 ~CommandObjectCommandsSource () {}
267
268 virtual const char*
GetRepeatCommand(Args & current_command_args,uint32_t index)269 GetRepeatCommand (Args ¤t_command_args, uint32_t index)
270 {
271 return "";
272 }
273
274 virtual int
HandleArgumentCompletion(Args & input,int & cursor_index,int & cursor_char_position,OptionElementVector & opt_element_vector,int match_start_point,int max_return_elements,bool & word_complete,StringList & matches)275 HandleArgumentCompletion (Args &input,
276 int &cursor_index,
277 int &cursor_char_position,
278 OptionElementVector &opt_element_vector,
279 int match_start_point,
280 int max_return_elements,
281 bool &word_complete,
282 StringList &matches)
283 {
284 std::string completion_str (input.GetArgumentAtIndex(cursor_index));
285 completion_str.erase (cursor_char_position);
286
287 CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
288 CommandCompletions::eDiskFileCompletion,
289 completion_str.c_str(),
290 match_start_point,
291 max_return_elements,
292 NULL,
293 word_complete,
294 matches);
295 return matches.GetSize();
296 }
297
298 virtual Options *
GetOptions()299 GetOptions ()
300 {
301 return &m_options;
302 }
303
304 protected:
305
306 class CommandOptions : public Options
307 {
308 public:
309
CommandOptions(CommandInterpreter & interpreter)310 CommandOptions (CommandInterpreter &interpreter) :
311 Options (interpreter),
312 m_stop_on_error (true)
313 {
314 }
315
316 virtual
~CommandOptions()317 ~CommandOptions (){}
318
319 virtual Error
SetOptionValue(uint32_t option_idx,const char * option_arg)320 SetOptionValue (uint32_t option_idx, const char *option_arg)
321 {
322 Error error;
323 const int short_option = m_getopt_table[option_idx].val;
324 bool success;
325
326 switch (short_option)
327 {
328 case 'e':
329 error = m_stop_on_error.SetValueFromCString(option_arg);
330 break;
331 case 'c':
332 m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
333 if (!success)
334 error.SetErrorStringWithFormat("invalid value for stop-on-continue: %s", option_arg);
335 break;
336 case 's':
337 m_silent_run = Args::StringToBoolean(option_arg, true, &success);
338 if (!success)
339 error.SetErrorStringWithFormat("invalid value for silent-run: %s", option_arg);
340 break;
341 default:
342 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
343 break;
344 }
345
346 return error;
347 }
348
349 void
OptionParsingStarting()350 OptionParsingStarting ()
351 {
352 m_stop_on_error.Clear();
353 m_silent_run = false;
354 m_stop_on_continue = true;
355 }
356
357 const OptionDefinition*
GetDefinitions()358 GetDefinitions ()
359 {
360 return g_option_table;
361 }
362
363 // Options table: Required for subclasses of Options.
364
365 static OptionDefinition g_option_table[];
366
367 // Instance variables to hold the values for command options.
368
369 OptionValueBoolean m_stop_on_error;
370 bool m_silent_run;
371 bool m_stop_on_continue;
372 };
373
374 bool
DoExecute(Args & command,CommandReturnObject & result)375 DoExecute(Args& command, CommandReturnObject &result)
376 {
377 const size_t argc = command.GetArgumentCount();
378 if (argc == 1)
379 {
380 const char *filename = command.GetArgumentAtIndex(0);
381
382 result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
383
384 FileSpec cmd_file (filename, true);
385 ExecutionContext *exe_ctx = NULL; // Just use the default context.
386 bool echo_commands = !m_options.m_silent_run;
387 bool print_results = true;
388 bool stop_on_error = m_options.m_stop_on_error.OptionWasSet() ? (bool)m_options.m_stop_on_error : m_interpreter.GetStopCmdSourceOnError();
389
390 m_interpreter.HandleCommandsFromFile (cmd_file,
391 exe_ctx,
392 m_options.m_stop_on_continue,
393 stop_on_error,
394 echo_commands,
395 print_results,
396 eLazyBoolCalculate,
397 result);
398 }
399 else
400 {
401 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
402 result.SetStatus (eReturnStatusFailed);
403 }
404 return result.Succeeded();
405
406 }
407 CommandOptions m_options;
408 };
409
410 OptionDefinition
411 CommandObjectCommandsSource::CommandOptions::g_option_table[] =
412 {
413 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
414 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
415 { LLDB_OPT_SET_ALL, false, "silent-run", 's', required_argument, NULL, 0, eArgTypeBoolean, "If true don't echo commands while executing."},
416 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
417 };
418
419 #pragma mark CommandObjectCommandsAlias
420 //-------------------------------------------------------------------------
421 // CommandObjectCommandsAlias
422 //-------------------------------------------------------------------------
423
424 static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
425 "You must define a Python function with this signature:\n"
426 "def my_command_impl(debugger, args, result, internal_dict):";
427
428
429 class CommandObjectCommandsAlias : public CommandObjectRaw
430 {
431
432
433 public:
CommandObjectCommandsAlias(CommandInterpreter & interpreter)434 CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
435 CommandObjectRaw (interpreter,
436 "command alias",
437 "Allow users to define their own debugger command abbreviations.",
438 NULL)
439 {
440 SetHelpLong(
441 "'alias' allows the user to create a short-cut or abbreviation for long \n\
442 commands, multi-word commands, and commands that take particular options. \n\
443 Below are some simple examples of how one might use the 'alias' command: \n\
444 \n 'command alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
445 // command. \n\
446 'command alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
447 // command. Since breakpoint commands are two-word \n\
448 // commands, the user will still need to enter the \n\
449 // second word after 'bp', e.g. 'bp enable' or \n\
450 // 'bp delete'. \n\
451 'command alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
452 // two-word command 'breakpoint list'. \n\
453 \nAn alias can include some options for the command, with the values either \n\
454 filled in at the time the alias is created, or specified as positional \n\
455 arguments, to be filled in when the alias is invoked. The following example \n\
456 shows how to create aliases with options: \n\
457 \n\
458 'command alias bfl breakpoint set -f %1 -l %2' \n\
459 \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
460 options already part of the alias. So if the user wants to set a breakpoint \n\
461 by file and line without explicitly having to use the -f and -l options, the \n\
462 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
463 for the actual arguments that will be passed when the alias command is used. \n\
464 The number in the placeholder refers to the position/order the actual value \n\
465 occupies when the alias is used. All the occurrences of '%1' in the alias \n\
466 will be replaced with the first argument, all the occurrences of '%2' in the \n\
467 alias will be replaced with the second argument, and so on. This also allows \n\
468 actual arguments to be used multiple times within an alias (see 'process \n\
469 launch' example below). \n\
470 Note: the positional arguments must substitute as whole words in the resultant\n\
471 command, so you can't at present do something like:\n\
472 \n\
473 command alias bcppfl breakpoint set -f %1.cpp -l %2\n\
474 \n\
475 to get the file extension \".cpp\" automatically appended. For more complex\n\
476 aliasing, use the \"command regex\" command instead.\n\
477 \nSo in the 'bfl' case, the actual file value will be \n\
478 filled in with the first argument following 'bfl' and the actual line number \n\
479 value will be filled in with the second argument. The user would use this \n\
480 alias as follows: \n\
481 \n (lldb) command alias bfl breakpoint set -f %1 -l %2 \n\
482 <... some time later ...> \n\
483 (lldb) bfl my-file.c 137 \n\
484 \nThis would be the same as if the user had entered \n\
485 'breakpoint set -f my-file.c -l 137'. \n\
486 \nAnother example: \n\
487 \n (lldb) command alias pltty process launch -s -o %1 -e %1 \n\
488 (lldb) pltty /dev/tty0 \n\
489 // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
490 \nIf the user always wanted to pass the same value to a particular option, the \n\
491 alias could be defined with that value directly in the alias as a constant, \n\
492 rather than using a positional placeholder: \n\
493 \n command alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
494 // 3 of whatever file is indicated. \n");
495
496 CommandArgumentEntry arg1;
497 CommandArgumentEntry arg2;
498 CommandArgumentEntry arg3;
499 CommandArgumentData alias_arg;
500 CommandArgumentData cmd_arg;
501 CommandArgumentData options_arg;
502
503 // Define the first (and only) variant of this arg.
504 alias_arg.arg_type = eArgTypeAliasName;
505 alias_arg.arg_repetition = eArgRepeatPlain;
506
507 // There is only one variant this argument could be; put it into the argument entry.
508 arg1.push_back (alias_arg);
509
510 // Define the first (and only) variant of this arg.
511 cmd_arg.arg_type = eArgTypeCommandName;
512 cmd_arg.arg_repetition = eArgRepeatPlain;
513
514 // There is only one variant this argument could be; put it into the argument entry.
515 arg2.push_back (cmd_arg);
516
517 // Define the first (and only) variant of this arg.
518 options_arg.arg_type = eArgTypeAliasOptions;
519 options_arg.arg_repetition = eArgRepeatOptional;
520
521 // There is only one variant this argument could be; put it into the argument entry.
522 arg3.push_back (options_arg);
523
524 // Push the data for the first argument into the m_arguments vector.
525 m_arguments.push_back (arg1);
526 m_arguments.push_back (arg2);
527 m_arguments.push_back (arg3);
528 }
529
~CommandObjectCommandsAlias()530 ~CommandObjectCommandsAlias ()
531 {
532 }
533
534 protected:
535 virtual bool
DoExecute(const char * raw_command_line,CommandReturnObject & result)536 DoExecute (const char *raw_command_line, CommandReturnObject &result)
537 {
538 Args args (raw_command_line);
539 std::string raw_command_string (raw_command_line);
540
541 size_t argc = args.GetArgumentCount();
542
543 if (argc < 2)
544 {
545 result.AppendError ("'alias' requires at least two arguments");
546 result.SetStatus (eReturnStatusFailed);
547 return false;
548 }
549
550 // Get the alias command.
551
552 const std::string alias_command = args.GetArgumentAtIndex (0);
553
554 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
555 // does the stripping itself.
556 size_t pos = raw_command_string.find (alias_command);
557 if (pos == 0)
558 {
559 raw_command_string = raw_command_string.substr (alias_command.size());
560 pos = raw_command_string.find_first_not_of (' ');
561 if ((pos != std::string::npos) && (pos > 0))
562 raw_command_string = raw_command_string.substr (pos);
563 }
564 else
565 {
566 result.AppendError ("Error parsing command string. No alias created.");
567 result.SetStatus (eReturnStatusFailed);
568 return false;
569 }
570
571
572 // Verify that the command is alias-able.
573 if (m_interpreter.CommandExists (alias_command.c_str()))
574 {
575 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
576 alias_command.c_str());
577 result.SetStatus (eReturnStatusFailed);
578 return false;
579 }
580
581 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
582 // raw_command_string is returned with the name of the command object stripped off the front.
583 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
584
585 if (!cmd_obj)
586 {
587 result.AppendErrorWithFormat ("invalid command given to 'alias'. '%s' does not begin with a valid command."
588 " No alias created.", raw_command_string.c_str());
589 result.SetStatus (eReturnStatusFailed);
590 return false;
591 }
592 else if (!cmd_obj->WantsRawCommandString ())
593 {
594 // Note that args was initialized with the original command, and has not been updated to this point.
595 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
596 return HandleAliasingNormalCommand (args, result);
597 }
598 else
599 {
600 return HandleAliasingRawCommand (alias_command, raw_command_string, *cmd_obj, result);
601 }
602 return result.Succeeded();
603 }
604
605 bool
HandleAliasingRawCommand(const std::string & alias_command,std::string & raw_command_string,CommandObject & cmd_obj,CommandReturnObject & result)606 HandleAliasingRawCommand (const std::string &alias_command, std::string &raw_command_string, CommandObject &cmd_obj, CommandReturnObject &result)
607 {
608 // Verify & handle any options/arguments passed to the alias command
609
610 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
611 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
612
613 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj.GetCommandName(), false);
614
615 if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
616 {
617 result.AppendError ("Unable to create requested alias.\n");
618 result.SetStatus (eReturnStatusFailed);
619 return false;
620 }
621
622 // Create the alias
623 if (m_interpreter.AliasExists (alias_command.c_str())
624 || m_interpreter.UserCommandExists (alias_command.c_str()))
625 {
626 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
627 if (temp_option_arg_sp.get())
628 {
629 if (option_arg_vector->size() == 0)
630 m_interpreter.RemoveAliasOptions (alias_command.c_str());
631 }
632 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
633 alias_command.c_str());
634 }
635
636 if (cmd_obj_sp)
637 {
638 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
639 if (option_arg_vector->size() > 0)
640 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
641 result.SetStatus (eReturnStatusSuccessFinishNoResult);
642 }
643 else
644 {
645 result.AppendError ("Unable to create requested alias.\n");
646 result.SetStatus (eReturnStatusFailed);
647 }
648 return result.Succeeded ();
649 }
650
651 bool
HandleAliasingNormalCommand(Args & args,CommandReturnObject & result)652 HandleAliasingNormalCommand (Args& args, CommandReturnObject &result)
653 {
654 size_t argc = args.GetArgumentCount();
655
656 if (argc < 2)
657 {
658 result.AppendError ("'alias' requires at least two arguments");
659 result.SetStatus (eReturnStatusFailed);
660 return false;
661 }
662
663 const std::string alias_command = args.GetArgumentAtIndex(0);
664 const std::string actual_command = args.GetArgumentAtIndex(1);
665
666 args.Shift(); // Shift the alias command word off the argument vector.
667 args.Shift(); // Shift the old command word off the argument vector.
668
669 // Verify that the command is alias'able, and get the appropriate command object.
670
671 if (m_interpreter.CommandExists (alias_command.c_str()))
672 {
673 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
674 alias_command.c_str());
675 result.SetStatus (eReturnStatusFailed);
676 }
677 else
678 {
679 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
680 CommandObjectSP subcommand_obj_sp;
681 bool use_subcommand = false;
682 if (command_obj_sp.get())
683 {
684 CommandObject *cmd_obj = command_obj_sp.get();
685 CommandObject *sub_cmd_obj = NULL;
686 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
687 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
688
689 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
690 {
691 if (argc >= 3)
692 {
693 const std::string sub_command = args.GetArgumentAtIndex(0);
694 assert (sub_command.length() != 0);
695 subcommand_obj_sp = cmd_obj->GetSubcommandSP (sub_command.c_str());
696 if (subcommand_obj_sp.get())
697 {
698 sub_cmd_obj = subcommand_obj_sp.get();
699 use_subcommand = true;
700 args.Shift(); // Shift the sub_command word off the argument vector.
701 cmd_obj = sub_cmd_obj;
702 }
703 else
704 {
705 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
706 "Unable to create alias.\n",
707 sub_command.c_str(), actual_command.c_str());
708 result.SetStatus (eReturnStatusFailed);
709 return false;
710 }
711 }
712 }
713
714 // Verify & handle any options/arguments passed to the alias command
715
716 if (args.GetArgumentCount () > 0)
717 {
718 CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
719 if (use_subcommand)
720 tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
721
722 std::string args_string;
723 args.GetCommandString (args_string);
724
725 if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
726 {
727 result.AppendError ("Unable to create requested alias.\n");
728 result.SetStatus (eReturnStatusFailed);
729 return false;
730 }
731 }
732
733 // Create the alias.
734
735 if (m_interpreter.AliasExists (alias_command.c_str())
736 || m_interpreter.UserCommandExists (alias_command.c_str()))
737 {
738 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
739 if (tmp_option_arg_sp.get())
740 {
741 if (option_arg_vector->size() == 0)
742 m_interpreter.RemoveAliasOptions (alias_command.c_str());
743 }
744 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
745 alias_command.c_str());
746 }
747
748 if (use_subcommand)
749 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
750 else
751 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
752 if (option_arg_vector->size() > 0)
753 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
754 result.SetStatus (eReturnStatusSuccessFinishNoResult);
755 }
756 else
757 {
758 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
759 result.SetStatus (eReturnStatusFailed);
760 return false;
761 }
762 }
763
764 return result.Succeeded();
765 }
766
767 };
768
769 #pragma mark CommandObjectCommandsUnalias
770 //-------------------------------------------------------------------------
771 // CommandObjectCommandsUnalias
772 //-------------------------------------------------------------------------
773
774 class CommandObjectCommandsUnalias : public CommandObjectParsed
775 {
776 public:
CommandObjectCommandsUnalias(CommandInterpreter & interpreter)777 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
778 CommandObjectParsed (interpreter,
779 "command unalias",
780 "Allow the user to remove/delete a user-defined command abbreviation.",
781 NULL)
782 {
783 CommandArgumentEntry arg;
784 CommandArgumentData alias_arg;
785
786 // Define the first (and only) variant of this arg.
787 alias_arg.arg_type = eArgTypeAliasName;
788 alias_arg.arg_repetition = eArgRepeatPlain;
789
790 // There is only one variant this argument could be; put it into the argument entry.
791 arg.push_back (alias_arg);
792
793 // Push the data for the first argument into the m_arguments vector.
794 m_arguments.push_back (arg);
795 }
796
~CommandObjectCommandsUnalias()797 ~CommandObjectCommandsUnalias()
798 {
799 }
800
801 protected:
802 bool
DoExecute(Args & args,CommandReturnObject & result)803 DoExecute (Args& args, CommandReturnObject &result)
804 {
805 CommandObject::CommandMap::iterator pos;
806 CommandObject *cmd_obj;
807
808 if (args.GetArgumentCount() != 0)
809 {
810 const char *command_name = args.GetArgumentAtIndex(0);
811 cmd_obj = m_interpreter.GetCommandObject(command_name);
812 if (cmd_obj)
813 {
814 if (m_interpreter.CommandExists (command_name))
815 {
816 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
817 command_name);
818 result.SetStatus (eReturnStatusFailed);
819 }
820 else
821 {
822
823 if (m_interpreter.RemoveAlias (command_name) == false)
824 {
825 if (m_interpreter.AliasExists (command_name))
826 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
827 command_name);
828 else
829 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
830 result.SetStatus (eReturnStatusFailed);
831 }
832 else
833 result.SetStatus (eReturnStatusSuccessFinishNoResult);
834 }
835 }
836 else
837 {
838 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
839 "current list of commands.\n",
840 command_name);
841 result.SetStatus (eReturnStatusFailed);
842 }
843 }
844 else
845 {
846 result.AppendError ("must call 'unalias' with a valid alias");
847 result.SetStatus (eReturnStatusFailed);
848 }
849
850 return result.Succeeded();
851 }
852 };
853
854 //-------------------------------------------------------------------------
855 // CommandObjectCommandsAddRegex
856 //-------------------------------------------------------------------------
857 #pragma mark CommandObjectCommandsAddRegex
858
859 class CommandObjectCommandsAddRegex : public CommandObjectParsed
860 {
861 public:
CommandObjectCommandsAddRegex(CommandInterpreter & interpreter)862 CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
863 CommandObjectParsed (interpreter,
864 "command regex",
865 "Allow the user to create a regular expression command.",
866 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
867 m_options (interpreter)
868 {
869 SetHelpLong(
870 "This command allows the user to create powerful regular expression commands\n"
871 "with substitutions. The regular expressions and substitutions are specified\n"
872 "using the regular exression substitution format of:\n"
873 "\n"
874 " s/<regex>/<subst>/\n"
875 "\n"
876 "<regex> is a regular expression that can use parenthesis to capture regular\n"
877 "expression input and substitute the captured matches in the output using %1\n"
878 "for the first match, %2 for the second, and so on.\n"
879 "\n"
880 "The regular expressions can all be specified on the command line if more than\n"
881 "one argument is provided. If just the command name is provided on the command\n"
882 "line, then the regular expressions and substitutions can be entered on separate\n"
883 " lines, followed by an empty line to terminate the command definition.\n"
884 "\n"
885 "EXAMPLES\n"
886 "\n"
887 "The following example will define a regular expression command named 'f' that\n"
888 "will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
889 "a number follows 'f':\n"
890 "\n"
891 " (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
892 "\n"
893 );
894 }
895
~CommandObjectCommandsAddRegex()896 ~CommandObjectCommandsAddRegex()
897 {
898 }
899
900
901 protected:
902 bool
DoExecute(Args & command,CommandReturnObject & result)903 DoExecute (Args& command, CommandReturnObject &result)
904 {
905 const size_t argc = command.GetArgumentCount();
906 if (argc == 0)
907 {
908 result.AppendError ("usage: 'command regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
909 result.SetStatus (eReturnStatusFailed);
910 }
911 else
912 {
913 Error error;
914 const char *name = command.GetArgumentAtIndex(0);
915 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
916 name,
917 m_options.GetHelp (),
918 m_options.GetSyntax (),
919 10));
920
921 if (argc == 1)
922 {
923 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
924 if (reader_sp)
925 {
926 error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
927 this, // baton
928 eInputReaderGranularityLine, // token size, to pass to callback function
929 NULL, // end token
930 "> ", // prompt
931 true); // echo input
932 if (error.Success())
933 {
934 m_interpreter.GetDebugger().PushInputReader (reader_sp);
935 result.SetStatus (eReturnStatusSuccessFinishNoResult);
936 return true;
937 }
938 }
939 }
940 else
941 {
942 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
943 {
944 llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx));
945 error = AppendRegexSubstitution (arg_strref);
946 if (error.Fail())
947 break;
948 }
949
950 if (error.Success())
951 {
952 AddRegexCommandToInterpreter();
953 }
954 }
955 if (error.Fail())
956 {
957 result.AppendError (error.AsCString());
958 result.SetStatus (eReturnStatusFailed);
959 }
960 }
961
962 return result.Succeeded();
963 }
964
965 Error
AppendRegexSubstitution(const llvm::StringRef & regex_sed)966 AppendRegexSubstitution (const llvm::StringRef ®ex_sed)
967 {
968 Error error;
969
970 if (m_regex_cmd_ap.get() == NULL)
971 {
972 error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
973 (int)regex_sed.size(),
974 regex_sed.data());
975 return error;
976 }
977
978 size_t regex_sed_size = regex_sed.size();
979
980 if (regex_sed_size <= 1)
981 {
982 error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
983 (int)regex_sed.size(),
984 regex_sed.data());
985 return error;
986 }
987
988 if (regex_sed[0] != 's')
989 {
990 error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
991 (int)regex_sed.size(),
992 regex_sed.data());
993 return error;
994 }
995 const size_t first_separator_char_pos = 1;
996 // use the char that follows 's' as the regex separator character
997 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
998 const char separator_char = regex_sed[first_separator_char_pos];
999 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
1000
1001 if (second_separator_char_pos == std::string::npos)
1002 {
1003 error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
1004 separator_char,
1005 (int)(regex_sed.size() - first_separator_char_pos - 1),
1006 regex_sed.data() + (first_separator_char_pos + 1));
1007 return error;
1008 }
1009
1010 const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
1011
1012 if (third_separator_char_pos == std::string::npos)
1013 {
1014 error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
1015 separator_char,
1016 (int)(regex_sed.size() - second_separator_char_pos - 1),
1017 regex_sed.data() + (second_separator_char_pos + 1));
1018 return error;
1019 }
1020
1021 if (third_separator_char_pos != regex_sed_size - 1)
1022 {
1023 // Make sure that everything that follows the last regex
1024 // separator char
1025 if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
1026 {
1027 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
1028 (int)third_separator_char_pos + 1,
1029 regex_sed.data(),
1030 (int)(regex_sed.size() - third_separator_char_pos - 1),
1031 regex_sed.data() + (third_separator_char_pos + 1));
1032 return error;
1033 }
1034
1035 }
1036 else if (first_separator_char_pos + 1 == second_separator_char_pos)
1037 {
1038 error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1039 separator_char,
1040 separator_char,
1041 separator_char,
1042 (int)regex_sed.size(),
1043 regex_sed.data());
1044 return error;
1045 }
1046 else if (second_separator_char_pos + 1 == third_separator_char_pos)
1047 {
1048 error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1049 separator_char,
1050 separator_char,
1051 separator_char,
1052 (int)regex_sed.size(),
1053 regex_sed.data());
1054 return error;
1055 }
1056 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
1057 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
1058 m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
1059 subst.c_str());
1060 return error;
1061 }
1062
1063 void
AddRegexCommandToInterpreter()1064 AddRegexCommandToInterpreter()
1065 {
1066 if (m_regex_cmd_ap.get())
1067 {
1068 if (m_regex_cmd_ap->HasRegexEntries())
1069 {
1070 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1071 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1072 }
1073 }
1074 }
1075
1076 void
InputReaderDidCancel()1077 InputReaderDidCancel()
1078 {
1079 m_regex_cmd_ap.reset();
1080 }
1081
1082 static size_t
InputReaderCallback(void * baton,InputReader & reader,lldb::InputReaderAction notification,const char * bytes,size_t bytes_len)1083 InputReaderCallback (void *baton,
1084 InputReader &reader,
1085 lldb::InputReaderAction notification,
1086 const char *bytes,
1087 size_t bytes_len)
1088 {
1089 CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
1090 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
1091
1092 switch (notification)
1093 {
1094 case eInputReaderActivate:
1095 if (!batch_mode)
1096 {
1097 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
1098 out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
1099 out_stream->Flush();
1100 }
1101 break;
1102 case eInputReaderReactivate:
1103 break;
1104
1105 case eInputReaderDeactivate:
1106 break;
1107
1108 case eInputReaderAsynchronousOutputWritten:
1109 break;
1110
1111 case eInputReaderGotToken:
1112 while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
1113 --bytes_len;
1114 if (bytes_len == 0)
1115 reader.SetIsDone(true);
1116 else if (bytes)
1117 {
1118 llvm::StringRef bytes_strref (bytes, bytes_len);
1119 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
1120 if (error.Fail())
1121 {
1122 if (!batch_mode)
1123 {
1124 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1125 out_stream->Printf("error: %s\n", error.AsCString());
1126 out_stream->Flush();
1127 }
1128 add_regex_cmd->InputReaderDidCancel ();
1129 reader.SetIsDone (true);
1130 }
1131 }
1132 break;
1133
1134 case eInputReaderInterrupt:
1135 {
1136 reader.SetIsDone (true);
1137 if (!batch_mode)
1138 {
1139 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1140 out_stream->PutCString("Regular expression command creations was cancelled.\n");
1141 out_stream->Flush();
1142 }
1143 add_regex_cmd->InputReaderDidCancel ();
1144 }
1145 break;
1146
1147 case eInputReaderEndOfFile:
1148 reader.SetIsDone (true);
1149 break;
1150
1151 case eInputReaderDone:
1152 add_regex_cmd->AddRegexCommandToInterpreter();
1153 break;
1154 }
1155
1156 return bytes_len;
1157 }
1158
1159 private:
1160 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1161
1162 class CommandOptions : public Options
1163 {
1164 public:
1165
CommandOptions(CommandInterpreter & interpreter)1166 CommandOptions (CommandInterpreter &interpreter) :
1167 Options (interpreter)
1168 {
1169 }
1170
1171 virtual
~CommandOptions()1172 ~CommandOptions (){}
1173
1174 virtual Error
SetOptionValue(uint32_t option_idx,const char * option_arg)1175 SetOptionValue (uint32_t option_idx, const char *option_arg)
1176 {
1177 Error error;
1178 const int short_option = m_getopt_table[option_idx].val;
1179
1180 switch (short_option)
1181 {
1182 case 'h':
1183 m_help.assign (option_arg);
1184 break;
1185 case 's':
1186 m_syntax.assign (option_arg);
1187 break;
1188
1189 default:
1190 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1191 break;
1192 }
1193
1194 return error;
1195 }
1196
1197 void
OptionParsingStarting()1198 OptionParsingStarting ()
1199 {
1200 m_help.clear();
1201 m_syntax.clear();
1202 }
1203
1204 const OptionDefinition*
GetDefinitions()1205 GetDefinitions ()
1206 {
1207 return g_option_table;
1208 }
1209
1210 // Options table: Required for subclasses of Options.
1211
1212 static OptionDefinition g_option_table[];
1213
1214 const char *
GetHelp()1215 GetHelp ()
1216 {
1217 if (m_help.empty())
1218 return NULL;
1219 return m_help.c_str();
1220 }
1221 const char *
GetSyntax()1222 GetSyntax ()
1223 {
1224 if (m_syntax.empty())
1225 return NULL;
1226 return m_syntax.c_str();
1227 }
1228 // Instance variables to hold the values for command options.
1229 protected:
1230 std::string m_help;
1231 std::string m_syntax;
1232 };
1233
1234 virtual Options *
GetOptions()1235 GetOptions ()
1236 {
1237 return &m_options;
1238 }
1239
1240 CommandOptions m_options;
1241 };
1242
1243 OptionDefinition
1244 CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1245 {
1246 { LLDB_OPT_SET_1, false, "help" , 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."},
1247 { LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
1248 { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
1249 };
1250
1251
1252 class CommandObjectPythonFunction : public CommandObjectRaw
1253 {
1254 private:
1255 std::string m_function_name;
1256 ScriptedCommandSynchronicity m_synchro;
1257 bool m_fetched_help_long;
1258
1259 public:
1260
CommandObjectPythonFunction(CommandInterpreter & interpreter,std::string name,std::string funct,ScriptedCommandSynchronicity synch)1261 CommandObjectPythonFunction (CommandInterpreter &interpreter,
1262 std::string name,
1263 std::string funct,
1264 ScriptedCommandSynchronicity synch) :
1265 CommandObjectRaw (interpreter,
1266 name.c_str(),
1267 (std::string("Run Python function ") + funct).c_str(),
1268 NULL),
1269 m_function_name(funct),
1270 m_synchro(synch),
1271 m_fetched_help_long(false)
1272 {
1273 }
1274
1275 virtual
~CommandObjectPythonFunction()1276 ~CommandObjectPythonFunction ()
1277 {
1278 }
1279
1280 virtual bool
IsRemovable() const1281 IsRemovable () const
1282 {
1283 return true;
1284 }
1285
1286 const std::string&
GetFunctionName()1287 GetFunctionName ()
1288 {
1289 return m_function_name;
1290 }
1291
1292 ScriptedCommandSynchronicity
GetSynchronicity()1293 GetSynchronicity ()
1294 {
1295 return m_synchro;
1296 }
1297
1298 virtual const char *
GetHelpLong()1299 GetHelpLong ()
1300 {
1301 if (!m_fetched_help_long)
1302 {
1303 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1304 if (scripter)
1305 {
1306 std::string docstring;
1307 m_fetched_help_long = scripter->GetDocumentationForItem(m_function_name.c_str(),docstring);
1308 if (!docstring.empty())
1309 SetHelpLong(docstring);
1310 }
1311 }
1312 return CommandObjectRaw::GetHelpLong();
1313 }
1314
1315 protected:
1316 virtual bool
DoExecute(const char * raw_command_line,CommandReturnObject & result)1317 DoExecute (const char *raw_command_line, CommandReturnObject &result)
1318 {
1319 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1320
1321 Error error;
1322
1323 result.SetStatus(eReturnStatusInvalid);
1324
1325 if (!scripter || scripter->RunScriptBasedCommand(m_function_name.c_str(),
1326 raw_command_line,
1327 m_synchro,
1328 result,
1329 error) == false)
1330 {
1331 result.AppendError(error.AsCString());
1332 result.SetStatus(eReturnStatusFailed);
1333 }
1334 else
1335 {
1336 // Don't change the status if the command already set it...
1337 if (result.GetStatus() == eReturnStatusInvalid)
1338 {
1339 if (result.GetOutputData() == NULL || result.GetOutputData()[0] == '\0')
1340 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1341 else
1342 result.SetStatus(eReturnStatusSuccessFinishResult);
1343 }
1344 }
1345
1346 return result.Succeeded();
1347 }
1348
1349 };
1350
1351 //-------------------------------------------------------------------------
1352 // CommandObjectCommandsScriptImport
1353 //-------------------------------------------------------------------------
1354
1355 class CommandObjectCommandsScriptImport : public CommandObjectParsed
1356 {
1357 public:
CommandObjectCommandsScriptImport(CommandInterpreter & interpreter)1358 CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) :
1359 CommandObjectParsed (interpreter,
1360 "command script import",
1361 "Import a scripting module in LLDB.",
1362 NULL),
1363 m_options(interpreter)
1364 {
1365 CommandArgumentEntry arg1;
1366 CommandArgumentData cmd_arg;
1367
1368 // Define the first (and only) variant of this arg.
1369 cmd_arg.arg_type = eArgTypeFilename;
1370 cmd_arg.arg_repetition = eArgRepeatPlain;
1371
1372 // There is only one variant this argument could be; put it into the argument entry.
1373 arg1.push_back (cmd_arg);
1374
1375 // Push the data for the first argument into the m_arguments vector.
1376 m_arguments.push_back (arg1);
1377 }
1378
~CommandObjectCommandsScriptImport()1379 ~CommandObjectCommandsScriptImport ()
1380 {
1381 }
1382
1383 virtual int
HandleArgumentCompletion(Args & input,int & cursor_index,int & cursor_char_position,OptionElementVector & opt_element_vector,int match_start_point,int max_return_elements,bool & word_complete,StringList & matches)1384 HandleArgumentCompletion (Args &input,
1385 int &cursor_index,
1386 int &cursor_char_position,
1387 OptionElementVector &opt_element_vector,
1388 int match_start_point,
1389 int max_return_elements,
1390 bool &word_complete,
1391 StringList &matches)
1392 {
1393 std::string completion_str (input.GetArgumentAtIndex(cursor_index));
1394 completion_str.erase (cursor_char_position);
1395
1396 CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
1397 CommandCompletions::eDiskFileCompletion,
1398 completion_str.c_str(),
1399 match_start_point,
1400 max_return_elements,
1401 NULL,
1402 word_complete,
1403 matches);
1404 return matches.GetSize();
1405 }
1406
1407 virtual Options *
GetOptions()1408 GetOptions ()
1409 {
1410 return &m_options;
1411 }
1412
1413 protected:
1414
1415 class CommandOptions : public Options
1416 {
1417 public:
1418
CommandOptions(CommandInterpreter & interpreter)1419 CommandOptions (CommandInterpreter &interpreter) :
1420 Options (interpreter)
1421 {
1422 }
1423
1424 virtual
~CommandOptions()1425 ~CommandOptions (){}
1426
1427 virtual Error
SetOptionValue(uint32_t option_idx,const char * option_arg)1428 SetOptionValue (uint32_t option_idx, const char *option_arg)
1429 {
1430 Error error;
1431 const int short_option = m_getopt_table[option_idx].val;
1432
1433 switch (short_option)
1434 {
1435 case 'r':
1436 m_allow_reload = true;
1437 break;
1438 default:
1439 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1440 break;
1441 }
1442
1443 return error;
1444 }
1445
1446 void
OptionParsingStarting()1447 OptionParsingStarting ()
1448 {
1449 m_allow_reload = true;
1450 }
1451
1452 const OptionDefinition*
GetDefinitions()1453 GetDefinitions ()
1454 {
1455 return g_option_table;
1456 }
1457
1458 // Options table: Required for subclasses of Options.
1459
1460 static OptionDefinition g_option_table[];
1461
1462 // Instance variables to hold the values for command options.
1463
1464 bool m_allow_reload;
1465 };
1466
1467 bool
DoExecute(Args & command,CommandReturnObject & result)1468 DoExecute (Args& command, CommandReturnObject &result)
1469 {
1470
1471 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1472 {
1473 result.AppendError ("only scripting language supported for module importing is currently Python");
1474 result.SetStatus (eReturnStatusFailed);
1475 return false;
1476 }
1477
1478 size_t argc = command.GetArgumentCount();
1479
1480 if (argc != 1)
1481 {
1482 result.AppendError ("'command script import' requires one argument");
1483 result.SetStatus (eReturnStatusFailed);
1484 return false;
1485 }
1486
1487 std::string path = command.GetArgumentAtIndex(0);
1488 Error error;
1489
1490 const bool init_session = true;
1491 // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that
1492 // commands won't ever be recursively invoked, but it's actually possible to craft
1493 // a Python script that does other "command script imports" in __lldb_init_module
1494 // the real fix is to have recursive commands possible with a CommandInvocation object
1495 // separate from the CommandObject itself, so that recursive command invocations
1496 // won't stomp on each other (wrt to execution contents, options, and more)
1497 m_exe_ctx.Clear();
1498 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(),
1499 m_options.m_allow_reload,
1500 init_session,
1501 error))
1502 {
1503 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1504 }
1505 else
1506 {
1507 result.AppendErrorWithFormat("module importing failed: %s", error.AsCString());
1508 result.SetStatus (eReturnStatusFailed);
1509 }
1510
1511 return result.Succeeded();
1512 }
1513
1514 CommandOptions m_options;
1515 };
1516
1517 OptionDefinition
1518 CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] =
1519 {
1520 { LLDB_OPT_SET_1, false, "allow-reload", 'r', no_argument, NULL, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."},
1521 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1522 };
1523
1524
1525 //-------------------------------------------------------------------------
1526 // CommandObjectCommandsScriptAdd
1527 //-------------------------------------------------------------------------
1528
1529 class CommandObjectCommandsScriptAdd : public CommandObjectParsed
1530 {
1531 public:
CommandObjectCommandsScriptAdd(CommandInterpreter & interpreter)1532 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
1533 CommandObjectParsed (interpreter,
1534 "command script add",
1535 "Add a scripted function as an LLDB command.",
1536 NULL),
1537 m_options (interpreter)
1538 {
1539 CommandArgumentEntry arg1;
1540 CommandArgumentData cmd_arg;
1541
1542 // Define the first (and only) variant of this arg.
1543 cmd_arg.arg_type = eArgTypeCommandName;
1544 cmd_arg.arg_repetition = eArgRepeatPlain;
1545
1546 // There is only one variant this argument could be; put it into the argument entry.
1547 arg1.push_back (cmd_arg);
1548
1549 // Push the data for the first argument into the m_arguments vector.
1550 m_arguments.push_back (arg1);
1551 }
1552
~CommandObjectCommandsScriptAdd()1553 ~CommandObjectCommandsScriptAdd ()
1554 {
1555 }
1556
1557 virtual Options *
GetOptions()1558 GetOptions ()
1559 {
1560 return &m_options;
1561 }
1562
1563 protected:
1564
1565 class CommandOptions : public Options
1566 {
1567 public:
1568
CommandOptions(CommandInterpreter & interpreter)1569 CommandOptions (CommandInterpreter &interpreter) :
1570 Options (interpreter)
1571 {
1572 }
1573
1574 virtual
~CommandOptions()1575 ~CommandOptions (){}
1576
1577 virtual Error
SetOptionValue(uint32_t option_idx,const char * option_arg)1578 SetOptionValue (uint32_t option_idx, const char *option_arg)
1579 {
1580 Error error;
1581 const int short_option = m_getopt_table[option_idx].val;
1582
1583 switch (short_option)
1584 {
1585 case 'f':
1586 m_funct_name = std::string(option_arg);
1587 break;
1588 case 's':
1589 m_synchronous = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
1590 if (!error.Success())
1591 error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg);
1592 break;
1593 default:
1594 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1595 break;
1596 }
1597
1598 return error;
1599 }
1600
1601 void
OptionParsingStarting()1602 OptionParsingStarting ()
1603 {
1604 m_funct_name = "";
1605 m_synchronous = eScriptedCommandSynchronicitySynchronous;
1606 }
1607
1608 const OptionDefinition*
GetDefinitions()1609 GetDefinitions ()
1610 {
1611 return g_option_table;
1612 }
1613
1614 // Options table: Required for subclasses of Options.
1615
1616 static OptionDefinition g_option_table[];
1617
1618 // Instance variables to hold the values for command options.
1619
1620 std::string m_funct_name;
1621 ScriptedCommandSynchronicity m_synchronous;
1622 };
1623
1624 private:
1625 class PythonAliasReader : public InputReaderEZ
1626 {
1627 private:
1628 CommandInterpreter& m_interpreter;
1629 std::string m_cmd_name;
1630 ScriptedCommandSynchronicity m_synchronous;
1631 StringList m_user_input;
1632 DISALLOW_COPY_AND_ASSIGN (PythonAliasReader);
1633 public:
PythonAliasReader(Debugger & debugger,CommandInterpreter & interpreter,std::string cmd_name,ScriptedCommandSynchronicity synch)1634 PythonAliasReader(Debugger& debugger,
1635 CommandInterpreter& interpreter,
1636 std::string cmd_name,
1637 ScriptedCommandSynchronicity synch) :
1638 InputReaderEZ(debugger),
1639 m_interpreter(interpreter),
1640 m_cmd_name(cmd_name),
1641 m_synchronous(synch),
1642 m_user_input()
1643 {}
1644
1645 virtual
~PythonAliasReader()1646 ~PythonAliasReader()
1647 {
1648 }
1649
ActivateHandler(HandlerData & data)1650 virtual void ActivateHandler(HandlerData& data)
1651 {
1652 StreamSP out_stream = data.GetOutStream();
1653 bool batch_mode = data.GetBatchMode();
1654 if (!batch_mode)
1655 {
1656 out_stream->Printf ("%s\n", g_python_command_instructions);
1657 if (data.reader.GetPrompt())
1658 out_stream->Printf ("%s", data.reader.GetPrompt());
1659 out_stream->Flush();
1660 }
1661 }
1662
ReactivateHandler(HandlerData & data)1663 virtual void ReactivateHandler(HandlerData& data)
1664 {
1665 StreamSP out_stream = data.GetOutStream();
1666 bool batch_mode = data.GetBatchMode();
1667 if (data.reader.GetPrompt() && !batch_mode)
1668 {
1669 out_stream->Printf ("%s", data.reader.GetPrompt());
1670 out_stream->Flush();
1671 }
1672 }
GotTokenHandler(HandlerData & data)1673 virtual void GotTokenHandler(HandlerData& data)
1674 {
1675 StreamSP out_stream = data.GetOutStream();
1676 bool batch_mode = data.GetBatchMode();
1677 if (data.bytes && data.bytes_len)
1678 {
1679 m_user_input.AppendString(data.bytes, data.bytes_len);
1680 }
1681 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
1682 {
1683 out_stream->Printf ("%s", data.reader.GetPrompt());
1684 out_stream->Flush();
1685 }
1686 }
InterruptHandler(HandlerData & data)1687 virtual void InterruptHandler(HandlerData& data)
1688 {
1689 StreamSP out_stream = data.GetOutStream();
1690 bool batch_mode = data.GetBatchMode();
1691 data.reader.SetIsDone (true);
1692 if (!batch_mode)
1693 {
1694 out_stream->Printf ("Warning: No script attached.\n");
1695 out_stream->Flush();
1696 }
1697 }
EOFHandler(HandlerData & data)1698 virtual void EOFHandler(HandlerData& data)
1699 {
1700 data.reader.SetIsDone (true);
1701 }
DoneHandler(HandlerData & data)1702 virtual void DoneHandler(HandlerData& data)
1703 {
1704 StreamSP out_stream = data.GetOutStream();
1705
1706 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1707 if (!interpreter)
1708 {
1709 out_stream->Printf ("Script interpreter missing: no script attached.\n");
1710 out_stream->Flush();
1711 return;
1712 }
1713 std::string funct_name_str;
1714 if (!interpreter->GenerateScriptAliasFunction (m_user_input,
1715 funct_name_str))
1716 {
1717 out_stream->Printf ("Unable to create function: no script attached.\n");
1718 out_stream->Flush();
1719 return;
1720 }
1721 if (funct_name_str.empty())
1722 {
1723 out_stream->Printf ("Unable to obtain a function name: no script attached.\n");
1724 out_stream->Flush();
1725 return;
1726 }
1727 // everything should be fine now, let's add this alias
1728
1729 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
1730 m_cmd_name,
1731 funct_name_str.c_str(),
1732 m_synchronous));
1733
1734 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true))
1735 {
1736 out_stream->Printf ("Unable to add selected command: no script attached.\n");
1737 out_stream->Flush();
1738 return;
1739 }
1740 }
1741 };
1742
1743 protected:
1744 bool
DoExecute(Args & command,CommandReturnObject & result)1745 DoExecute (Args& command, CommandReturnObject &result)
1746 {
1747
1748 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1749 {
1750 result.AppendError ("only scripting language supported for scripted commands is currently Python");
1751 result.SetStatus (eReturnStatusFailed);
1752 return false;
1753 }
1754
1755 size_t argc = command.GetArgumentCount();
1756
1757 if (argc != 1)
1758 {
1759 result.AppendError ("'command script add' requires one argument");
1760 result.SetStatus (eReturnStatusFailed);
1761 return false;
1762 }
1763
1764 std::string cmd_name = command.GetArgumentAtIndex(0);
1765
1766 if (m_options.m_funct_name.empty())
1767 {
1768 InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(),
1769 m_interpreter,
1770 cmd_name,
1771 m_options.m_synchronous));
1772
1773 if (reader_sp)
1774 {
1775
1776 InputReaderEZ::InitializationParameters ipr;
1777
1778 Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt(" ")));
1779 if (err.Success())
1780 {
1781 m_interpreter.GetDebugger().PushInputReader (reader_sp);
1782 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1783 }
1784 else
1785 {
1786 result.AppendError (err.AsCString());
1787 result.SetStatus (eReturnStatusFailed);
1788 }
1789 }
1790 else
1791 {
1792 result.AppendError("out of memory");
1793 result.SetStatus (eReturnStatusFailed);
1794 }
1795 }
1796 else
1797 {
1798 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,
1799 cmd_name,
1800 m_options.m_funct_name,
1801 m_options.m_synchronous));
1802 if (m_interpreter.AddUserCommand(cmd_name, new_cmd, true))
1803 {
1804 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1805 }
1806 else
1807 {
1808 result.AppendError("cannot add command");
1809 result.SetStatus (eReturnStatusFailed);
1810 }
1811 }
1812
1813 return result.Succeeded();
1814
1815 }
1816
1817 CommandOptions m_options;
1818 };
1819
1820 static OptionEnumValueElement g_script_synchro_type[] =
1821 {
1822 { eScriptedCommandSynchronicitySynchronous, "synchronous", "Run synchronous"},
1823 { eScriptedCommandSynchronicityAsynchronous, "asynchronous", "Run asynchronous"},
1824 { eScriptedCommandSynchronicityCurrentValue, "current", "Do not alter current setting"},
1825 { 0, NULL, NULL }
1826 };
1827
1828 OptionDefinition
1829 CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
1830 {
1831 { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."},
1832 { LLDB_OPT_SET_1, false, "synchronicity", 's', required_argument, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."},
1833 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1834 };
1835
1836 //-------------------------------------------------------------------------
1837 // CommandObjectCommandsScriptList
1838 //-------------------------------------------------------------------------
1839
1840 class CommandObjectCommandsScriptList : public CommandObjectParsed
1841 {
1842 private:
1843
1844 public:
CommandObjectCommandsScriptList(CommandInterpreter & interpreter)1845 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
1846 CommandObjectParsed (interpreter,
1847 "command script list",
1848 "List defined scripted commands.",
1849 NULL)
1850 {
1851 }
1852
~CommandObjectCommandsScriptList()1853 ~CommandObjectCommandsScriptList ()
1854 {
1855 }
1856
1857 bool
DoExecute(Args & command,CommandReturnObject & result)1858 DoExecute (Args& command, CommandReturnObject &result)
1859 {
1860
1861 m_interpreter.GetHelp(result,
1862 CommandInterpreter::eCommandTypesUserDef);
1863
1864 result.SetStatus (eReturnStatusSuccessFinishResult);
1865
1866 return true;
1867
1868
1869 }
1870 };
1871
1872 //-------------------------------------------------------------------------
1873 // CommandObjectCommandsScriptClear
1874 //-------------------------------------------------------------------------
1875
1876 class CommandObjectCommandsScriptClear : public CommandObjectParsed
1877 {
1878 private:
1879
1880 public:
CommandObjectCommandsScriptClear(CommandInterpreter & interpreter)1881 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
1882 CommandObjectParsed (interpreter,
1883 "command script clear",
1884 "Delete all scripted commands.",
1885 NULL)
1886 {
1887 }
1888
~CommandObjectCommandsScriptClear()1889 ~CommandObjectCommandsScriptClear ()
1890 {
1891 }
1892
1893 protected:
1894 bool
DoExecute(Args & command,CommandReturnObject & result)1895 DoExecute (Args& command, CommandReturnObject &result)
1896 {
1897
1898 m_interpreter.RemoveAllUser();
1899
1900 result.SetStatus (eReturnStatusSuccessFinishResult);
1901
1902 return true;
1903 }
1904 };
1905
1906 //-------------------------------------------------------------------------
1907 // CommandObjectCommandsScriptDelete
1908 //-------------------------------------------------------------------------
1909
1910 class CommandObjectCommandsScriptDelete : public CommandObjectParsed
1911 {
1912 public:
CommandObjectCommandsScriptDelete(CommandInterpreter & interpreter)1913 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) :
1914 CommandObjectParsed (interpreter,
1915 "command script delete",
1916 "Delete a scripted command.",
1917 NULL)
1918 {
1919 CommandArgumentEntry arg1;
1920 CommandArgumentData cmd_arg;
1921
1922 // Define the first (and only) variant of this arg.
1923 cmd_arg.arg_type = eArgTypeCommandName;
1924 cmd_arg.arg_repetition = eArgRepeatPlain;
1925
1926 // There is only one variant this argument could be; put it into the argument entry.
1927 arg1.push_back (cmd_arg);
1928
1929 // Push the data for the first argument into the m_arguments vector.
1930 m_arguments.push_back (arg1);
1931 }
1932
~CommandObjectCommandsScriptDelete()1933 ~CommandObjectCommandsScriptDelete ()
1934 {
1935 }
1936
1937 protected:
1938 bool
DoExecute(Args & command,CommandReturnObject & result)1939 DoExecute (Args& command, CommandReturnObject &result)
1940 {
1941
1942 size_t argc = command.GetArgumentCount();
1943
1944 if (argc != 1)
1945 {
1946 result.AppendError ("'command script delete' requires one argument");
1947 result.SetStatus (eReturnStatusFailed);
1948 return false;
1949 }
1950
1951 const char* cmd_name = command.GetArgumentAtIndex(0);
1952
1953 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name))
1954 {
1955 m_interpreter.RemoveUser(cmd_name);
1956 result.SetStatus (eReturnStatusSuccessFinishResult);
1957 }
1958 else
1959 {
1960 result.AppendErrorWithFormat ("command %s not found", cmd_name);
1961 result.SetStatus (eReturnStatusFailed);
1962 }
1963
1964 return result.Succeeded();
1965
1966 }
1967 };
1968
1969 #pragma mark CommandObjectMultiwordCommandsScript
1970
1971 //-------------------------------------------------------------------------
1972 // CommandObjectMultiwordCommandsScript
1973 //-------------------------------------------------------------------------
1974
1975 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword
1976 {
1977 public:
CommandObjectMultiwordCommandsScript(CommandInterpreter & interpreter)1978 CommandObjectMultiwordCommandsScript (CommandInterpreter &interpreter) :
1979 CommandObjectMultiword (interpreter,
1980 "command script",
1981 "A set of commands for managing or customizing script commands.",
1982 "command script <subcommand> [<subcommand-options>]")
1983 {
1984 LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
1985 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
1986 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
1987 LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
1988 LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));
1989 }
1990
~CommandObjectMultiwordCommandsScript()1991 ~CommandObjectMultiwordCommandsScript ()
1992 {
1993 }
1994
1995 };
1996
1997
1998 #pragma mark CommandObjectMultiwordCommands
1999
2000 //-------------------------------------------------------------------------
2001 // CommandObjectMultiwordCommands
2002 //-------------------------------------------------------------------------
2003
CommandObjectMultiwordCommands(CommandInterpreter & interpreter)2004 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
2005 CommandObjectMultiword (interpreter,
2006 "command",
2007 "A set of commands for managing or customizing the debugger commands.",
2008 "command <subcommand> [<subcommand-options>]")
2009 {
2010 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
2011 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
2012 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
2013 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
2014 LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
2015 LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
2016 }
2017
~CommandObjectMultiwordCommands()2018 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
2019 {
2020 }
2021
2022