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