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