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:
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 
50     ~CommandObjectCommandsHistory () {}
51 
52     virtual Options *
53     GetOptions ()
54     {
55         return &m_options;
56     }
57 
58 protected:
59 
60     class CommandOptions : public Options
61     {
62     public:
63 
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
74         ~CommandOptions (){}
75 
76         virtual Error
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
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*
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
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:
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 
262     ~CommandObjectCommandsSource () {}
263 
264     virtual const char*
265     GetRepeatCommand (Args &current_command_args, uint32_t index)
266     {
267         return "";
268     }
269 
270     virtual int
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 *
295     GetOptions ()
296     {
297         return &m_options;
298     }
299 
300 protected:
301 
302     class CommandOptions : public Options
303     {
304     public:
305 
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
315         ~CommandOptions (){}
316 
317         virtual Error
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
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*
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
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:
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 
556     ~CommandObjectCommandsAlias ()
557     {
558     }
559 
560 protected:
561     virtual bool
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
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
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:
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 
823     ~CommandObjectCommandsUnalias()
824     {
825     }
826 
827 protected:
828     bool
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:
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 
916     ~CommandObjectCommandsDelete()
917     {
918     }
919 
920 protected:
921     bool
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:
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 
1003     ~CommandObjectCommandsAddRegex()
1004     {
1005     }
1006 
1007 
1008 protected:
1009 
1010     void
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
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
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
1123     AppendRegexSubstitution (const llvm::StringRef &regex_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
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 
1248          CommandOptions (CommandInterpreter &interpreter) :
1249             Options (interpreter)
1250          {
1251          }
1252 
1253          virtual
1254          ~CommandOptions (){}
1255 
1256          virtual Error
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
1280          OptionParsingStarting ()
1281          {
1282              m_help.clear();
1283              m_syntax.clear();
1284          }
1285 
1286          const OptionDefinition*
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 *
1297          GetHelp ()
1298          {
1299              if (m_help.empty())
1300                  return NULL;
1301              return m_help.c_str();
1302          }
1303          const char *
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 *
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 
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
1367     ~CommandObjectPythonFunction ()
1368     {
1369     }
1370 
1371     virtual bool
1372     IsRemovable () const
1373     {
1374         return true;
1375     }
1376 
1377     const std::string&
1378     GetFunctionName ()
1379     {
1380         return m_function_name;
1381     }
1382 
1383     ScriptedCommandSynchronicity
1384     GetSynchronicity ()
1385     {
1386         return m_synchro;
1387     }
1388 
1389     virtual const char *
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
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 
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
1474     ~CommandObjectScriptingObject ()
1475     {
1476     }
1477 
1478     virtual bool
1479     IsRemovable () const
1480     {
1481         return true;
1482     }
1483 
1484     StructuredData::GenericSP
1485     GetImplementingObject ()
1486     {
1487         return m_cmd_obj_sp;
1488     }
1489 
1490     ScriptedCommandSynchronicity
1491     GetSynchronicity ()
1492     {
1493         return m_synchro;
1494     }
1495 
1496     virtual const char *
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 *
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
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:
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 
1595     ~CommandObjectCommandsScriptImport ()
1596     {
1597     }
1598 
1599     virtual int
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 *
1624     GetOptions ()
1625     {
1626         return &m_options;
1627     }
1628 
1629 protected:
1630 
1631     class CommandOptions : public Options
1632     {
1633     public:
1634 
1635         CommandOptions (CommandInterpreter &interpreter) :
1636             Options (interpreter)
1637         {
1638         }
1639 
1640         virtual
1641         ~CommandOptions (){}
1642 
1643         virtual Error
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
1663         OptionParsingStarting ()
1664         {
1665             m_allow_reload = true;
1666         }
1667 
1668         const OptionDefinition*
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
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:
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 
1775     ~CommandObjectCommandsScriptAdd ()
1776     {
1777     }
1778 
1779     virtual Options *
1780     GetOptions ()
1781     {
1782         return &m_options;
1783     }
1784 
1785 protected:
1786 
1787     class CommandOptions : public Options
1788     {
1789     public:
1790 
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
1801         ~CommandOptions (){}
1802 
1803         virtual Error
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
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*
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
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
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
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:
2059     CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
2060     CommandObjectParsed (interpreter,
2061                    "command script list",
2062                    "List defined scripted commands.",
2063                    NULL)
2064     {
2065     }
2066 
2067     ~CommandObjectCommandsScriptList ()
2068     {
2069     }
2070 
2071     bool
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:
2095     CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
2096         CommandObjectParsed (interpreter,
2097                              "command script clear",
2098                              "Delete all scripted commands.",
2099                              NULL)
2100     {
2101     }
2102 
2103     ~CommandObjectCommandsScriptClear ()
2104     {
2105     }
2106 
2107 protected:
2108     bool
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:
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 
2147     ~CommandObjectCommandsScriptDelete ()
2148     {
2149     }
2150 
2151 protected:
2152     bool
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:
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 
2205     ~CommandObjectMultiwordCommandsScript ()
2206     {
2207     }
2208 
2209 };
2210 
2211 
2212 #pragma mark CommandObjectMultiwordCommands
2213 
2214 //-------------------------------------------------------------------------
2215 // CommandObjectMultiwordCommands
2216 //-------------------------------------------------------------------------
2217 
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 
2233 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
2234 {
2235 }
2236 
2237