1e9a5627eSJohnny Chen //===-- CommandObjectWatchpointCommand.cpp ----------------------*- C++ -*-===//
2e9a5627eSJohnny Chen //
3e9a5627eSJohnny Chen //                     The LLVM Compiler Infrastructure
4e9a5627eSJohnny Chen //
5e9a5627eSJohnny Chen // This file is distributed under the University of Illinois Open Source
6e9a5627eSJohnny Chen // License. See LICENSE.TXT for details.
7e9a5627eSJohnny Chen //
8e9a5627eSJohnny Chen //===----------------------------------------------------------------------===//
9e9a5627eSJohnny Chen 
10e9a5627eSJohnny Chen // C Includes
11e9a5627eSJohnny Chen // C++ Includes
12e9a5627eSJohnny Chen 
13e9a5627eSJohnny Chen 
14e9a5627eSJohnny Chen #include "CommandObjectWatchpointCommand.h"
15e9a5627eSJohnny Chen #include "CommandObjectWatchpoint.h"
16e9a5627eSJohnny Chen 
1744d93782SGreg Clayton #include "lldb/Core/IOHandler.h"
18e9a5627eSJohnny Chen #include "lldb/Interpreter/CommandInterpreter.h"
19e9a5627eSJohnny Chen #include "lldb/Interpreter/CommandReturnObject.h"
20e9a5627eSJohnny Chen #include "lldb/Target/Target.h"
21e9a5627eSJohnny Chen #include "lldb/Target/Thread.h"
22e9a5627eSJohnny Chen #include "lldb/Breakpoint/Watchpoint.h"
23e9a5627eSJohnny Chen #include "lldb/Breakpoint/StoppointCallbackContext.h"
24e9a5627eSJohnny Chen #include "lldb/Core/State.h"
25e9a5627eSJohnny Chen 
26e9a5627eSJohnny Chen #include <vector>
27e9a5627eSJohnny Chen 
28e9a5627eSJohnny Chen using namespace lldb;
29e9a5627eSJohnny Chen using namespace lldb_private;
30e9a5627eSJohnny Chen 
31e9a5627eSJohnny Chen //-------------------------------------------------------------------------
32e9a5627eSJohnny Chen // CommandObjectWatchpointCommandAdd
33e9a5627eSJohnny Chen //-------------------------------------------------------------------------
34e9a5627eSJohnny Chen 
35e9a5627eSJohnny Chen 
3644d93782SGreg Clayton class CommandObjectWatchpointCommandAdd :
3744d93782SGreg Clayton     public CommandObjectParsed,
3844d93782SGreg Clayton     public IOHandlerDelegateMultiline
39e9a5627eSJohnny Chen {
40e9a5627eSJohnny Chen public:
41e9a5627eSJohnny Chen 
42e9a5627eSJohnny Chen     CommandObjectWatchpointCommandAdd (CommandInterpreter &interpreter) :
43e9a5627eSJohnny Chen         CommandObjectParsed (interpreter,
44e9a5627eSJohnny Chen                              "add",
45e9a5627eSJohnny Chen                              "Add a set of commands to a watchpoint, to be executed whenever the watchpoint is hit.",
46e9a5627eSJohnny Chen                              NULL),
47c3d874a5SGreg Clayton         IOHandlerDelegateMultiline("DONE", IOHandlerDelegate::Completion::LLDBCommand),
48e9a5627eSJohnny Chen         m_options (interpreter)
49e9a5627eSJohnny Chen     {
50e9a5627eSJohnny Chen         SetHelpLong (
51*ea671fbdSKate Stone R"(
52*ea671fbdSKate Stone General information about entering watchpoint commands
53*ea671fbdSKate Stone ------------------------------------------------------
54*ea671fbdSKate Stone 
55*ea671fbdSKate Stone )" "This command will prompt for commands to be executed when the specified \
56*ea671fbdSKate Stone watchpoint is hit.  Each command is typed on its own line following the '> ' \
57*ea671fbdSKate Stone prompt until 'DONE' is entered." R"(
58*ea671fbdSKate Stone 
59*ea671fbdSKate Stone )" "Syntactic errors may not be detected when initially entered, and many \
60*ea671fbdSKate Stone malformed commands can silently fail when executed.  If your watchpoint commands \
61*ea671fbdSKate Stone do not appear to be executing, double-check the command syntax." R"(
62*ea671fbdSKate Stone 
63*ea671fbdSKate Stone )" "Note: You may enter any debugger command exactly as you would at the debugger \
64*ea671fbdSKate Stone prompt.  There is no limit to the number of commands supplied, but do NOT enter \
65*ea671fbdSKate Stone more than one command per line." R"(
66*ea671fbdSKate Stone 
67*ea671fbdSKate Stone Special information about PYTHON watchpoint commands
68*ea671fbdSKate Stone ----------------------------------------------------
69*ea671fbdSKate Stone 
70*ea671fbdSKate Stone )" "You may enter either one or more lines of Python, including function \
71*ea671fbdSKate Stone definitions or calls to functions that will have been imported by the time \
72*ea671fbdSKate Stone the code executes.  Single line watchpoint commands will be interpreted 'as is' \
73*ea671fbdSKate Stone when the watchpoint is hit.  Multiple lines of Python will be wrapped in a \
74*ea671fbdSKate Stone generated function, and a call to the function will be attached to the watchpoint." R"(
75*ea671fbdSKate Stone 
76*ea671fbdSKate Stone This auto-generated function is passed in three arguments:
77*ea671fbdSKate Stone 
78*ea671fbdSKate Stone     frame:  an lldb.SBFrame object for the frame which hit the watchpoint.
79*ea671fbdSKate Stone 
80*ea671fbdSKate Stone     wp:     the watchpoint that was hit.
81*ea671fbdSKate Stone 
82*ea671fbdSKate Stone )" "When specifying a python function with the --python-function option, you need \
83*ea671fbdSKate Stone to supply the function name prepended by the module name:" R"(
84*ea671fbdSKate Stone 
85*ea671fbdSKate Stone     --python-function myutils.watchpoint_callback
86*ea671fbdSKate Stone 
87*ea671fbdSKate Stone The function itself must have the following prototype:
88*ea671fbdSKate Stone 
89*ea671fbdSKate Stone def watchpoint_callback(frame, wp):
90*ea671fbdSKate Stone   # Your code goes here
91*ea671fbdSKate Stone 
92*ea671fbdSKate Stone )" "The arguments are the same as the arguments passed to generated functions as \
93*ea671fbdSKate Stone described above.  Note that the global variable 'lldb.frame' will NOT be updated when \
94*ea671fbdSKate Stone this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
95*ea671fbdSKate Stone can get you to the thread via frame.GetThread(), the thread can get you to the \
96*ea671fbdSKate Stone process via thread.GetProcess(), and the process can get you back to the target \
97*ea671fbdSKate Stone via process.GetTarget()." R"(
98*ea671fbdSKate Stone 
99*ea671fbdSKate Stone )" "Important Note: As Python code gets collected into functions, access to global \
100*ea671fbdSKate Stone variables requires explicit scoping using the 'global' keyword.  Be sure to use correct \
101*ea671fbdSKate Stone Python syntax, including indentation, when entering Python watchpoint commands." R"(
102*ea671fbdSKate Stone 
103*ea671fbdSKate Stone Example Python one-line watchpoint command:
104*ea671fbdSKate Stone 
105*ea671fbdSKate Stone (lldb) watchpoint command add -s python 1
106*ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
107*ea671fbdSKate Stone > print "Hit this watchpoint!"
108*ea671fbdSKate Stone > DONE
109*ea671fbdSKate Stone 
110*ea671fbdSKate Stone As a convenience, this also works for a short Python one-liner:
111*ea671fbdSKate Stone 
112*ea671fbdSKate Stone (lldb) watchpoint command add -s python 1 -o 'import time; print time.asctime()'
113*ea671fbdSKate Stone (lldb) run
114*ea671fbdSKate Stone Launching '.../a.out'  (x86_64)
115*ea671fbdSKate Stone (lldb) Fri Sep 10 12:17:45 2010
116*ea671fbdSKate Stone Process 21778 Stopped
117*ea671fbdSKate Stone * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread
118*ea671fbdSKate Stone   36
119*ea671fbdSKate Stone   37   	int c(int val)
120*ea671fbdSKate Stone   38   	{
121*ea671fbdSKate Stone   39 ->	    return val + 3;
122*ea671fbdSKate Stone   40   	}
123*ea671fbdSKate Stone   41
124*ea671fbdSKate Stone   42   	int main (int argc, char const *argv[])
125*ea671fbdSKate Stone 
126*ea671fbdSKate Stone Example multiple line Python watchpoint command, using function definition:
127*ea671fbdSKate Stone 
128*ea671fbdSKate Stone (lldb) watchpoint command add -s python 1
129*ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
130*ea671fbdSKate Stone > def watchpoint_output (wp_no):
131*ea671fbdSKate Stone >     out_string = "Hit watchpoint number " + repr (wp_no)
132*ea671fbdSKate Stone >     print out_string
133*ea671fbdSKate Stone >     return True
134*ea671fbdSKate Stone > watchpoint_output (1)
135*ea671fbdSKate Stone > DONE
136*ea671fbdSKate Stone 
137*ea671fbdSKate Stone Example multiple line Python watchpoint command, using 'loose' Python:
138*ea671fbdSKate Stone 
139*ea671fbdSKate Stone (lldb) watchpoint command add -s p 1
140*ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
141*ea671fbdSKate Stone > global wp_count
142*ea671fbdSKate Stone > wp_count = wp_count + 1
143*ea671fbdSKate Stone > print "Hit this watchpoint " + repr(wp_count) + " times!"
144*ea671fbdSKate Stone > DONE
145*ea671fbdSKate Stone 
146*ea671fbdSKate Stone )" "In this case, since there is a reference to a global variable, \
147*ea671fbdSKate Stone 'wp_count', you will also need to make sure 'wp_count' exists and is \
148*ea671fbdSKate Stone initialized:" R"(
149*ea671fbdSKate Stone 
150*ea671fbdSKate Stone (lldb) script
151*ea671fbdSKate Stone >>> wp_count = 0
152*ea671fbdSKate Stone >>> quit()
153*ea671fbdSKate Stone 
154*ea671fbdSKate Stone )" "Final Note: A warning that no watchpoint command was generated when there \
155*ea671fbdSKate Stone are no syntax errors may indicate that a function was declared but never called."
156*ea671fbdSKate Stone         );
157e9a5627eSJohnny Chen 
158e9a5627eSJohnny Chen         CommandArgumentEntry arg;
159e9a5627eSJohnny Chen         CommandArgumentData wp_id_arg;
160e9a5627eSJohnny Chen 
161e9a5627eSJohnny Chen         // Define the first (and only) variant of this arg.
162e9a5627eSJohnny Chen         wp_id_arg.arg_type = eArgTypeWatchpointID;
163e9a5627eSJohnny Chen         wp_id_arg.arg_repetition = eArgRepeatPlain;
164e9a5627eSJohnny Chen 
165e9a5627eSJohnny Chen         // There is only one variant this argument could be; put it into the argument entry.
166e9a5627eSJohnny Chen         arg.push_back (wp_id_arg);
167e9a5627eSJohnny Chen 
168e9a5627eSJohnny Chen         // Push the data for the first argument into the m_arguments vector.
169e9a5627eSJohnny Chen         m_arguments.push_back (arg);
170e9a5627eSJohnny Chen     }
171e9a5627eSJohnny Chen 
172e9a5627eSJohnny Chen     virtual
173e9a5627eSJohnny Chen     ~CommandObjectWatchpointCommandAdd () {}
174e9a5627eSJohnny Chen 
175e9a5627eSJohnny Chen     virtual Options *
176e9a5627eSJohnny Chen     GetOptions ()
177e9a5627eSJohnny Chen     {
178e9a5627eSJohnny Chen         return &m_options;
179e9a5627eSJohnny Chen     }
180e9a5627eSJohnny Chen 
18144d93782SGreg Clayton     virtual void
18244d93782SGreg Clayton     IOHandlerActivated (IOHandler &io_handler)
18344d93782SGreg Clayton     {
18444d93782SGreg Clayton         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
18544d93782SGreg Clayton         if (output_sp)
18644d93782SGreg Clayton         {
18744d93782SGreg Clayton             output_sp->PutCString("Enter your debugger command(s).  Type 'DONE' to end.\n");
18844d93782SGreg Clayton             output_sp->Flush();
18944d93782SGreg Clayton         }
19044d93782SGreg Clayton     }
19144d93782SGreg Clayton 
19244d93782SGreg Clayton 
19344d93782SGreg Clayton     virtual void
19444d93782SGreg Clayton     IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
19544d93782SGreg Clayton     {
19644d93782SGreg Clayton         io_handler.SetIsDone(true);
19744d93782SGreg Clayton 
19844d93782SGreg Clayton         // The WatchpointOptions object is owned by the watchpoint or watchpoint location
19944d93782SGreg Clayton         WatchpointOptions *wp_options = (WatchpointOptions *) io_handler.GetUserData();
20044d93782SGreg Clayton         if (wp_options)
20144d93782SGreg Clayton         {
20244d93782SGreg Clayton             std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
20344d93782SGreg Clayton             if (data_ap.get())
20444d93782SGreg Clayton             {
20544d93782SGreg Clayton                 data_ap->user_source.SplitIntoLines(line);
20644d93782SGreg Clayton                 BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
20744d93782SGreg Clayton                 wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
20844d93782SGreg Clayton             }
20944d93782SGreg Clayton         }
21044d93782SGreg Clayton     }
21144d93782SGreg Clayton 
212e9a5627eSJohnny Chen     void
213e9a5627eSJohnny Chen     CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
214e9a5627eSJohnny Chen                                              CommandReturnObject &result)
215e9a5627eSJohnny Chen     {
21644d93782SGreg Clayton         m_interpreter.GetLLDBCommandsFromIOHandler ("> ",           // Prompt
21744d93782SGreg Clayton                                                     *this,          // IOHandlerDelegate
21844d93782SGreg Clayton                                                     true,           // Run IOHandler in async mode
21944d93782SGreg Clayton                                                     wp_options);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
220e9a5627eSJohnny Chen     }
221e9a5627eSJohnny Chen 
222e9a5627eSJohnny Chen     /// Set a one-liner as the callback for the watchpoint.
223e9a5627eSJohnny Chen     void
224e9a5627eSJohnny Chen     SetWatchpointCommandCallback (WatchpointOptions *wp_options,
225e9a5627eSJohnny Chen                                   const char *oneliner)
226e9a5627eSJohnny Chen     {
2277b0992d9SGreg Clayton         std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
228e9a5627eSJohnny Chen 
229e9a5627eSJohnny Chen         // It's necessary to set both user_source and script_source to the oneliner.
230e9a5627eSJohnny Chen         // The former is used to generate callback description (as in watchpoint command list)
231e9a5627eSJohnny Chen         // while the latter is used for Python to interpret during the actual callback.
232e9a5627eSJohnny Chen         data_ap->user_source.AppendString (oneliner);
233e9a5627eSJohnny Chen         data_ap->script_source.assign (oneliner);
234e9a5627eSJohnny Chen         data_ap->stop_on_error = m_options.m_stop_on_error;
235e9a5627eSJohnny Chen 
236e9a5627eSJohnny Chen         BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
237e9a5627eSJohnny Chen         wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
238e9a5627eSJohnny Chen 
239e9a5627eSJohnny Chen         return;
240e9a5627eSJohnny Chen     }
241e9a5627eSJohnny Chen 
242e9a5627eSJohnny Chen     static bool
243e9a5627eSJohnny Chen     WatchpointOptionsCallbackFunction (void *baton,
244e9a5627eSJohnny Chen                                        StoppointCallbackContext *context,
245e9a5627eSJohnny Chen                                        lldb::user_id_t watch_id)
246e9a5627eSJohnny Chen     {
247e9a5627eSJohnny Chen         bool ret_value = true;
248e9a5627eSJohnny Chen         if (baton == NULL)
249e9a5627eSJohnny Chen             return true;
250e9a5627eSJohnny Chen 
251e9a5627eSJohnny Chen 
252e9a5627eSJohnny Chen         WatchpointOptions::CommandData *data = (WatchpointOptions::CommandData *) baton;
253e9a5627eSJohnny Chen         StringList &commands = data->user_source;
254e9a5627eSJohnny Chen 
255e9a5627eSJohnny Chen         if (commands.GetSize() > 0)
256e9a5627eSJohnny Chen         {
257e9a5627eSJohnny Chen             ExecutionContext exe_ctx (context->exe_ctx_ref);
258e9a5627eSJohnny Chen             Target *target = exe_ctx.GetTargetPtr();
259e9a5627eSJohnny Chen             if (target)
260e9a5627eSJohnny Chen             {
261e9a5627eSJohnny Chen                 CommandReturnObject result;
262e9a5627eSJohnny Chen                 Debugger &debugger = target->GetDebugger();
263e9a5627eSJohnny Chen                 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
264e9a5627eSJohnny Chen                 // if the debugger is set up that way.
265e9a5627eSJohnny Chen 
266e9a5627eSJohnny Chen                 StreamSP output_stream (debugger.GetAsyncOutputStream());
267e9a5627eSJohnny Chen                 StreamSP error_stream (debugger.GetAsyncErrorStream());
268e9a5627eSJohnny Chen                 result.SetImmediateOutputStream (output_stream);
269e9a5627eSJohnny Chen                 result.SetImmediateErrorStream (error_stream);
270e9a5627eSJohnny Chen 
27126c7bf93SJim Ingham                 CommandInterpreterRunOptions options;
27226c7bf93SJim Ingham                 options.SetStopOnContinue (true);
27326c7bf93SJim Ingham                 options.SetStopOnError (data->stop_on_error);
27426c7bf93SJim Ingham                 options.SetEchoCommands (false);
27526c7bf93SJim Ingham                 options.SetPrintResults (true);
27626c7bf93SJim Ingham                 options.SetAddToHistory (false);
277e9a5627eSJohnny Chen 
278e9a5627eSJohnny Chen                 debugger.GetCommandInterpreter().HandleCommands (commands,
279e9a5627eSJohnny Chen                                                                  &exe_ctx,
28026c7bf93SJim Ingham                                                                  options,
281e9a5627eSJohnny Chen                                                                  result);
282e9a5627eSJohnny Chen                 result.GetImmediateOutputStream()->Flush();
283e9a5627eSJohnny Chen                 result.GetImmediateErrorStream()->Flush();
284e9a5627eSJohnny Chen            }
285e9a5627eSJohnny Chen         }
286e9a5627eSJohnny Chen         return ret_value;
287e9a5627eSJohnny Chen     }
288e9a5627eSJohnny Chen 
289e9a5627eSJohnny Chen     class CommandOptions : public Options
290e9a5627eSJohnny Chen     {
291e9a5627eSJohnny Chen     public:
292e9a5627eSJohnny Chen 
293e9a5627eSJohnny Chen         CommandOptions (CommandInterpreter &interpreter) :
294e9a5627eSJohnny Chen             Options (interpreter),
295e9a5627eSJohnny Chen             m_use_commands (false),
296e9a5627eSJohnny Chen             m_use_script_language (false),
297e9a5627eSJohnny Chen             m_script_language (eScriptLanguageNone),
298e9a5627eSJohnny Chen             m_use_one_liner (false),
299e9a5627eSJohnny Chen             m_one_liner(),
300e9a5627eSJohnny Chen             m_function_name()
301e9a5627eSJohnny Chen         {
302e9a5627eSJohnny Chen         }
303e9a5627eSJohnny Chen 
304e9a5627eSJohnny Chen         virtual
305e9a5627eSJohnny Chen         ~CommandOptions () {}
306e9a5627eSJohnny Chen 
307e9a5627eSJohnny Chen         virtual Error
308e9a5627eSJohnny Chen         SetOptionValue (uint32_t option_idx, const char *option_arg)
309e9a5627eSJohnny Chen         {
310e9a5627eSJohnny Chen             Error error;
3113bcdfc0eSGreg Clayton             const int short_option = m_getopt_table[option_idx].val;
312e9a5627eSJohnny Chen 
313e9a5627eSJohnny Chen             switch (short_option)
314e9a5627eSJohnny Chen             {
315e9a5627eSJohnny Chen             case 'o':
316e9a5627eSJohnny Chen                 m_use_one_liner = true;
317e9a5627eSJohnny Chen                 m_one_liner = option_arg;
318e9a5627eSJohnny Chen                 break;
319e9a5627eSJohnny Chen 
320e9a5627eSJohnny Chen             case 's':
321e9a5627eSJohnny Chen                 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
322e9a5627eSJohnny Chen                                                                                      g_option_table[option_idx].enum_values,
323e9a5627eSJohnny Chen                                                                                      eScriptLanguageNone,
324e9a5627eSJohnny Chen                                                                                      error);
325e9a5627eSJohnny Chen 
326e9a5627eSJohnny Chen                 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
327e9a5627eSJohnny Chen                 {
328e9a5627eSJohnny Chen                     m_use_script_language = true;
329e9a5627eSJohnny Chen                 }
330e9a5627eSJohnny Chen                 else
331e9a5627eSJohnny Chen                 {
332e9a5627eSJohnny Chen                     m_use_script_language = false;
333e9a5627eSJohnny Chen                 }
334e9a5627eSJohnny Chen                 break;
335e9a5627eSJohnny Chen 
336e9a5627eSJohnny Chen             case 'e':
337e9a5627eSJohnny Chen                 {
338e9a5627eSJohnny Chen                     bool success = false;
339e9a5627eSJohnny Chen                     m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
340e9a5627eSJohnny Chen                     if (!success)
341e9a5627eSJohnny Chen                         error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
342e9a5627eSJohnny Chen                 }
343e9a5627eSJohnny Chen                 break;
344e9a5627eSJohnny Chen 
345e9a5627eSJohnny Chen             case 'F':
346e9a5627eSJohnny Chen                 {
347e9a5627eSJohnny Chen                     m_use_one_liner = false;
348e9a5627eSJohnny Chen                     m_use_script_language = true;
349e9a5627eSJohnny Chen                     m_function_name.assign(option_arg);
350e9a5627eSJohnny Chen                 }
351e9a5627eSJohnny Chen                 break;
352e9a5627eSJohnny Chen 
353e9a5627eSJohnny Chen             default:
354e9a5627eSJohnny Chen                 break;
355e9a5627eSJohnny Chen             }
356e9a5627eSJohnny Chen             return error;
357e9a5627eSJohnny Chen         }
358e9a5627eSJohnny Chen         void
359e9a5627eSJohnny Chen         OptionParsingStarting ()
360e9a5627eSJohnny Chen         {
361e9a5627eSJohnny Chen             m_use_commands = true;
362e9a5627eSJohnny Chen             m_use_script_language = false;
363e9a5627eSJohnny Chen             m_script_language = eScriptLanguageNone;
364e9a5627eSJohnny Chen 
365e9a5627eSJohnny Chen             m_use_one_liner = false;
366e9a5627eSJohnny Chen             m_stop_on_error = true;
367e9a5627eSJohnny Chen             m_one_liner.clear();
368e9a5627eSJohnny Chen             m_function_name.clear();
369e9a5627eSJohnny Chen         }
370e9a5627eSJohnny Chen 
371e9a5627eSJohnny Chen         const OptionDefinition*
372e9a5627eSJohnny Chen         GetDefinitions ()
373e9a5627eSJohnny Chen         {
374e9a5627eSJohnny Chen             return g_option_table;
375e9a5627eSJohnny Chen         }
376e9a5627eSJohnny Chen 
377e9a5627eSJohnny Chen         // Options table: Required for subclasses of Options.
378e9a5627eSJohnny Chen 
379e9a5627eSJohnny Chen         static OptionDefinition g_option_table[];
380e9a5627eSJohnny Chen 
381e9a5627eSJohnny Chen         // Instance variables to hold the values for command options.
382e9a5627eSJohnny Chen 
383e9a5627eSJohnny Chen         bool m_use_commands;
384e9a5627eSJohnny Chen         bool m_use_script_language;
385e9a5627eSJohnny Chen         lldb::ScriptLanguage m_script_language;
386e9a5627eSJohnny Chen 
387e9a5627eSJohnny Chen         // Instance variables to hold the values for one_liner options.
388e9a5627eSJohnny Chen         bool m_use_one_liner;
389e9a5627eSJohnny Chen         std::string m_one_liner;
390e9a5627eSJohnny Chen         bool m_stop_on_error;
391e9a5627eSJohnny Chen         std::string m_function_name;
392e9a5627eSJohnny Chen     };
393e9a5627eSJohnny Chen 
394e9a5627eSJohnny Chen protected:
395e9a5627eSJohnny Chen     virtual bool
396e9a5627eSJohnny Chen     DoExecute (Args& command, CommandReturnObject &result)
397e9a5627eSJohnny Chen     {
398e9a5627eSJohnny Chen         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
399e9a5627eSJohnny Chen 
400e9a5627eSJohnny Chen         if (target == NULL)
401e9a5627eSJohnny Chen         {
402e9a5627eSJohnny Chen             result.AppendError ("There is not a current executable; there are no watchpoints to which to add commands");
403e9a5627eSJohnny Chen             result.SetStatus (eReturnStatusFailed);
404e9a5627eSJohnny Chen             return false;
405e9a5627eSJohnny Chen         }
406e9a5627eSJohnny Chen 
407e9a5627eSJohnny Chen         const WatchpointList &watchpoints = target->GetWatchpointList();
408e9a5627eSJohnny Chen         size_t num_watchpoints = watchpoints.GetSize();
409e9a5627eSJohnny Chen 
410e9a5627eSJohnny Chen         if (num_watchpoints == 0)
411e9a5627eSJohnny Chen         {
412e9a5627eSJohnny Chen             result.AppendError ("No watchpoints exist to have commands added");
413e9a5627eSJohnny Chen             result.SetStatus (eReturnStatusFailed);
414e9a5627eSJohnny Chen             return false;
415e9a5627eSJohnny Chen         }
416e9a5627eSJohnny Chen 
417e9a5627eSJohnny Chen         if (m_options.m_use_script_language == false && m_options.m_function_name.size())
418e9a5627eSJohnny Chen         {
419e9a5627eSJohnny Chen             result.AppendError ("need to enable scripting to have a function run as a watchpoint command");
420e9a5627eSJohnny Chen             result.SetStatus (eReturnStatusFailed);
421e9a5627eSJohnny Chen             return false;
422e9a5627eSJohnny Chen         }
423e9a5627eSJohnny Chen 
424e9a5627eSJohnny Chen         std::vector<uint32_t> valid_wp_ids;
425b0b4513eSJim Ingham         if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
426e9a5627eSJohnny Chen         {
427e9a5627eSJohnny Chen             result.AppendError("Invalid watchpoints specification.");
428e9a5627eSJohnny Chen             result.SetStatus(eReturnStatusFailed);
429e9a5627eSJohnny Chen             return false;
430e9a5627eSJohnny Chen         }
431e9a5627eSJohnny Chen 
432e9a5627eSJohnny Chen         result.SetStatus(eReturnStatusSuccessFinishNoResult);
433e9a5627eSJohnny Chen         const size_t count = valid_wp_ids.size();
434e9a5627eSJohnny Chen         for (size_t i = 0; i < count; ++i)
435e9a5627eSJohnny Chen         {
436e9a5627eSJohnny Chen             uint32_t cur_wp_id = valid_wp_ids.at (i);
437e9a5627eSJohnny Chen             if (cur_wp_id != LLDB_INVALID_WATCH_ID)
438e9a5627eSJohnny Chen             {
439e9a5627eSJohnny Chen                 Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
440e9a5627eSJohnny Chen                 // Sanity check wp first.
441e9a5627eSJohnny Chen                 if (wp == NULL) continue;
442e9a5627eSJohnny Chen 
443e9a5627eSJohnny Chen                 WatchpointOptions *wp_options = wp->GetOptions();
444e9a5627eSJohnny Chen                 // Skip this watchpoint if wp_options is not good.
445e9a5627eSJohnny Chen                 if (wp_options == NULL) continue;
446e9a5627eSJohnny Chen 
447e9a5627eSJohnny Chen                 // If we are using script language, get the script interpreter
448e9a5627eSJohnny Chen                 // in order to set or collect command callback.  Otherwise, call
449e9a5627eSJohnny Chen                 // the methods associated with this object.
450e9a5627eSJohnny Chen                 if (m_options.m_use_script_language)
451e9a5627eSJohnny Chen                 {
452e9a5627eSJohnny Chen                     // Special handling for one-liner specified inline.
453e9a5627eSJohnny Chen                     if (m_options.m_use_one_liner)
454e9a5627eSJohnny Chen                     {
455e9a5627eSJohnny Chen                         m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback (wp_options,
456e9a5627eSJohnny Chen                                                                                             m_options.m_one_liner.c_str());
457e9a5627eSJohnny Chen                     }
458e9a5627eSJohnny Chen                     // Special handling for using a Python function by name
459e9a5627eSJohnny Chen                     // instead of extending the watchpoint callback data structures, we just automatize
460e9a5627eSJohnny Chen                     // what the user would do manually: make their watchpoint command be a function call
461e9a5627eSJohnny Chen                     else if (m_options.m_function_name.size())
462e9a5627eSJohnny Chen                     {
463e9a5627eSJohnny Chen                         std::string oneliner(m_options.m_function_name);
464e9a5627eSJohnny Chen                         oneliner += "(frame, wp, internal_dict)";
465e9a5627eSJohnny Chen                         m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback (wp_options,
466e9a5627eSJohnny Chen                                                                                             oneliner.c_str());
467e9a5627eSJohnny Chen                     }
468e9a5627eSJohnny Chen                     else
469e9a5627eSJohnny Chen                     {
470e9a5627eSJohnny Chen                         m_interpreter.GetScriptInterpreter()->CollectDataForWatchpointCommandCallback (wp_options,
471e9a5627eSJohnny Chen                                                                                                        result);
472e9a5627eSJohnny Chen                     }
473e9a5627eSJohnny Chen                 }
474e9a5627eSJohnny Chen                 else
475e9a5627eSJohnny Chen                 {
476e9a5627eSJohnny Chen                     // Special handling for one-liner specified inline.
477e9a5627eSJohnny Chen                     if (m_options.m_use_one_liner)
478e9a5627eSJohnny Chen                         SetWatchpointCommandCallback (wp_options,
479e9a5627eSJohnny Chen                                                       m_options.m_one_liner.c_str());
480e9a5627eSJohnny Chen                     else
481e9a5627eSJohnny Chen                         CollectDataForWatchpointCommandCallback (wp_options,
482e9a5627eSJohnny Chen                                                                  result);
483e9a5627eSJohnny Chen                 }
484e9a5627eSJohnny Chen             }
485e9a5627eSJohnny Chen         }
486e9a5627eSJohnny Chen 
487e9a5627eSJohnny Chen         return result.Succeeded();
488e9a5627eSJohnny Chen     }
489e9a5627eSJohnny Chen 
490e9a5627eSJohnny Chen private:
491e9a5627eSJohnny Chen     CommandOptions m_options;
492e9a5627eSJohnny Chen };
493e9a5627eSJohnny Chen 
494e9a5627eSJohnny Chen 
495e9a5627eSJohnny Chen // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
496e9a5627eSJohnny Chen // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
497e9a5627eSJohnny Chen 
498e9a5627eSJohnny Chen static OptionEnumValueElement
499e9a5627eSJohnny Chen g_script_option_enumeration[4] =
500e9a5627eSJohnny Chen {
501e9a5627eSJohnny Chen     { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
502e9a5627eSJohnny Chen     { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
503e9a5627eSJohnny Chen     { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
504e9a5627eSJohnny Chen     { 0,                      NULL,              NULL }
505e9a5627eSJohnny Chen };
506e9a5627eSJohnny Chen 
507e9a5627eSJohnny Chen OptionDefinition
508e9a5627eSJohnny Chen CommandObjectWatchpointCommandAdd::CommandOptions::g_option_table[] =
509e9a5627eSJohnny Chen {
510d37221dcSZachary Turner     { LLDB_OPT_SET_1,   false, "one-liner",       'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
511e9a5627eSJohnny Chen         "Specify a one-line watchpoint command inline. Be sure to surround it with quotes." },
512e9a5627eSJohnny Chen 
513d37221dcSZachary Turner     { LLDB_OPT_SET_ALL, false, "stop-on-error",   'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
514e9a5627eSJohnny Chen         "Specify whether watchpoint command execution should terminate on error." },
515e9a5627eSJohnny Chen 
516d37221dcSZachary Turner     { LLDB_OPT_SET_ALL, false, "script-type",     's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone,
517e9a5627eSJohnny Chen         "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
518e9a5627eSJohnny Chen 
519d37221dcSZachary Turner     { LLDB_OPT_SET_2,   false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,
520e9a5627eSJohnny Chen         "Give the name of a Python function to run as command for this watchpoint. Be sure to give a module name if appropriate."},
521e9a5627eSJohnny Chen 
522d37221dcSZachary Turner     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
523e9a5627eSJohnny Chen };
524e9a5627eSJohnny Chen 
525e9a5627eSJohnny Chen //-------------------------------------------------------------------------
526e9a5627eSJohnny Chen // CommandObjectWatchpointCommandDelete
527e9a5627eSJohnny Chen //-------------------------------------------------------------------------
528e9a5627eSJohnny Chen 
529e9a5627eSJohnny Chen class CommandObjectWatchpointCommandDelete : public CommandObjectParsed
530e9a5627eSJohnny Chen {
531e9a5627eSJohnny Chen public:
532e9a5627eSJohnny Chen     CommandObjectWatchpointCommandDelete (CommandInterpreter &interpreter) :
533e9a5627eSJohnny Chen         CommandObjectParsed (interpreter,
534e9a5627eSJohnny Chen                              "delete",
535e9a5627eSJohnny Chen                              "Delete the set of commands from a watchpoint.",
536e9a5627eSJohnny Chen                              NULL)
537e9a5627eSJohnny Chen     {
538e9a5627eSJohnny Chen         CommandArgumentEntry arg;
539e9a5627eSJohnny Chen         CommandArgumentData wp_id_arg;
540e9a5627eSJohnny Chen 
541e9a5627eSJohnny Chen         // Define the first (and only) variant of this arg.
542e9a5627eSJohnny Chen         wp_id_arg.arg_type = eArgTypeWatchpointID;
543e9a5627eSJohnny Chen         wp_id_arg.arg_repetition = eArgRepeatPlain;
544e9a5627eSJohnny Chen 
545e9a5627eSJohnny Chen         // There is only one variant this argument could be; put it into the argument entry.
546e9a5627eSJohnny Chen         arg.push_back (wp_id_arg);
547e9a5627eSJohnny Chen 
548e9a5627eSJohnny Chen         // Push the data for the first argument into the m_arguments vector.
549e9a5627eSJohnny Chen         m_arguments.push_back (arg);
550e9a5627eSJohnny Chen     }
551e9a5627eSJohnny Chen 
552e9a5627eSJohnny Chen 
553e9a5627eSJohnny Chen     virtual
554e9a5627eSJohnny Chen     ~CommandObjectWatchpointCommandDelete () {}
555e9a5627eSJohnny Chen 
556e9a5627eSJohnny Chen protected:
557e9a5627eSJohnny Chen     virtual bool
558e9a5627eSJohnny Chen     DoExecute (Args& command, CommandReturnObject &result)
559e9a5627eSJohnny Chen     {
560e9a5627eSJohnny Chen         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
561e9a5627eSJohnny Chen 
562e9a5627eSJohnny Chen         if (target == NULL)
563e9a5627eSJohnny Chen         {
564e9a5627eSJohnny Chen             result.AppendError ("There is not a current executable; there are no watchpoints from which to delete commands");
565e9a5627eSJohnny Chen             result.SetStatus (eReturnStatusFailed);
566e9a5627eSJohnny Chen             return false;
567e9a5627eSJohnny Chen         }
568e9a5627eSJohnny Chen 
569e9a5627eSJohnny Chen         const WatchpointList &watchpoints = target->GetWatchpointList();
570e9a5627eSJohnny Chen         size_t num_watchpoints = watchpoints.GetSize();
571e9a5627eSJohnny Chen 
572e9a5627eSJohnny Chen         if (num_watchpoints == 0)
573e9a5627eSJohnny Chen         {
574e9a5627eSJohnny Chen             result.AppendError ("No watchpoints exist to have commands deleted");
575e9a5627eSJohnny Chen             result.SetStatus (eReturnStatusFailed);
576e9a5627eSJohnny Chen             return false;
577e9a5627eSJohnny Chen         }
578e9a5627eSJohnny Chen 
579e9a5627eSJohnny Chen         if (command.GetArgumentCount() == 0)
580e9a5627eSJohnny Chen         {
581e9a5627eSJohnny Chen             result.AppendError ("No watchpoint specified from which to delete the commands");
582e9a5627eSJohnny Chen             result.SetStatus (eReturnStatusFailed);
583e9a5627eSJohnny Chen             return false;
584e9a5627eSJohnny Chen         }
585e9a5627eSJohnny Chen 
586e9a5627eSJohnny Chen         std::vector<uint32_t> valid_wp_ids;
587b0b4513eSJim Ingham         if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
588e9a5627eSJohnny Chen         {
589e9a5627eSJohnny Chen             result.AppendError("Invalid watchpoints specification.");
590e9a5627eSJohnny Chen             result.SetStatus(eReturnStatusFailed);
591e9a5627eSJohnny Chen             return false;
592e9a5627eSJohnny Chen         }
593e9a5627eSJohnny Chen 
594e9a5627eSJohnny Chen         result.SetStatus(eReturnStatusSuccessFinishNoResult);
595e9a5627eSJohnny Chen         const size_t count = valid_wp_ids.size();
596e9a5627eSJohnny Chen         for (size_t i = 0; i < count; ++i)
597e9a5627eSJohnny Chen         {
598e9a5627eSJohnny Chen             uint32_t cur_wp_id = valid_wp_ids.at (i);
599e9a5627eSJohnny Chen             if (cur_wp_id != LLDB_INVALID_WATCH_ID)
600e9a5627eSJohnny Chen             {
601e9a5627eSJohnny Chen                 Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
602e9a5627eSJohnny Chen                 if (wp)
603e9a5627eSJohnny Chen                     wp->ClearCallback();
604e9a5627eSJohnny Chen             }
605e9a5627eSJohnny Chen             else
606e9a5627eSJohnny Chen             {
607e9a5627eSJohnny Chen                 result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n",
608e9a5627eSJohnny Chen                                              cur_wp_id);
609e9a5627eSJohnny Chen                 result.SetStatus (eReturnStatusFailed);
610e9a5627eSJohnny Chen                 return false;
611e9a5627eSJohnny Chen             }
612e9a5627eSJohnny Chen         }
613e9a5627eSJohnny Chen         return result.Succeeded();
614e9a5627eSJohnny Chen     }
615e9a5627eSJohnny Chen };
616e9a5627eSJohnny Chen 
617e9a5627eSJohnny Chen //-------------------------------------------------------------------------
618e9a5627eSJohnny Chen // CommandObjectWatchpointCommandList
619e9a5627eSJohnny Chen //-------------------------------------------------------------------------
620e9a5627eSJohnny Chen 
621e9a5627eSJohnny Chen class CommandObjectWatchpointCommandList : public CommandObjectParsed
622e9a5627eSJohnny Chen {
623e9a5627eSJohnny Chen public:
624e9a5627eSJohnny Chen     CommandObjectWatchpointCommandList (CommandInterpreter &interpreter) :
625e9a5627eSJohnny Chen         CommandObjectParsed (interpreter,
626e9a5627eSJohnny Chen                              "list",
627e9a5627eSJohnny Chen                              "List the script or set of commands to be executed when the watchpoint is hit.",
628e9a5627eSJohnny Chen                               NULL)
629e9a5627eSJohnny Chen     {
630e9a5627eSJohnny Chen         CommandArgumentEntry arg;
631e9a5627eSJohnny Chen         CommandArgumentData wp_id_arg;
632e9a5627eSJohnny Chen 
633e9a5627eSJohnny Chen         // Define the first (and only) variant of this arg.
634e9a5627eSJohnny Chen         wp_id_arg.arg_type = eArgTypeWatchpointID;
635e9a5627eSJohnny Chen         wp_id_arg.arg_repetition = eArgRepeatPlain;
636e9a5627eSJohnny Chen 
637e9a5627eSJohnny Chen         // There is only one variant this argument could be; put it into the argument entry.
638e9a5627eSJohnny Chen         arg.push_back (wp_id_arg);
639e9a5627eSJohnny Chen 
640e9a5627eSJohnny Chen         // Push the data for the first argument into the m_arguments vector.
641e9a5627eSJohnny Chen         m_arguments.push_back (arg);
642e9a5627eSJohnny Chen     }
643e9a5627eSJohnny Chen 
644e9a5627eSJohnny Chen     virtual
645e9a5627eSJohnny Chen     ~CommandObjectWatchpointCommandList () {}
646e9a5627eSJohnny Chen 
647e9a5627eSJohnny Chen protected:
648e9a5627eSJohnny Chen     virtual bool
649e9a5627eSJohnny Chen     DoExecute (Args& command,
650e9a5627eSJohnny Chen              CommandReturnObject &result)
651e9a5627eSJohnny Chen     {
652e9a5627eSJohnny Chen         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
653e9a5627eSJohnny Chen 
654e9a5627eSJohnny Chen         if (target == NULL)
655e9a5627eSJohnny Chen         {
656e9a5627eSJohnny Chen             result.AppendError ("There is not a current executable; there are no watchpoints for which to list commands");
657e9a5627eSJohnny Chen             result.SetStatus (eReturnStatusFailed);
658e9a5627eSJohnny Chen             return false;
659e9a5627eSJohnny Chen         }
660e9a5627eSJohnny Chen 
661e9a5627eSJohnny Chen         const WatchpointList &watchpoints = target->GetWatchpointList();
662e9a5627eSJohnny Chen         size_t num_watchpoints = watchpoints.GetSize();
663e9a5627eSJohnny Chen 
664e9a5627eSJohnny Chen         if (num_watchpoints == 0)
665e9a5627eSJohnny Chen         {
666e9a5627eSJohnny Chen             result.AppendError ("No watchpoints exist for which to list commands");
667e9a5627eSJohnny Chen             result.SetStatus (eReturnStatusFailed);
668e9a5627eSJohnny Chen             return false;
669e9a5627eSJohnny Chen         }
670e9a5627eSJohnny Chen 
671e9a5627eSJohnny Chen         if (command.GetArgumentCount() == 0)
672e9a5627eSJohnny Chen         {
673e9a5627eSJohnny Chen             result.AppendError ("No watchpoint specified for which to list the commands");
674e9a5627eSJohnny Chen             result.SetStatus (eReturnStatusFailed);
675e9a5627eSJohnny Chen             return false;
676e9a5627eSJohnny Chen         }
677e9a5627eSJohnny Chen 
678e9a5627eSJohnny Chen         std::vector<uint32_t> valid_wp_ids;
679b0b4513eSJim Ingham         if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
680e9a5627eSJohnny Chen         {
681e9a5627eSJohnny Chen             result.AppendError("Invalid watchpoints specification.");
682e9a5627eSJohnny Chen             result.SetStatus(eReturnStatusFailed);
683e9a5627eSJohnny Chen             return false;
684e9a5627eSJohnny Chen         }
685e9a5627eSJohnny Chen 
686e9a5627eSJohnny Chen         result.SetStatus(eReturnStatusSuccessFinishNoResult);
687e9a5627eSJohnny Chen         const size_t count = valid_wp_ids.size();
688e9a5627eSJohnny Chen         for (size_t i = 0; i < count; ++i)
689e9a5627eSJohnny Chen         {
690e9a5627eSJohnny Chen             uint32_t cur_wp_id = valid_wp_ids.at (i);
691e9a5627eSJohnny Chen             if (cur_wp_id != LLDB_INVALID_WATCH_ID)
692e9a5627eSJohnny Chen             {
693e9a5627eSJohnny Chen                 Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
694e9a5627eSJohnny Chen 
695e9a5627eSJohnny Chen                 if (wp)
696e9a5627eSJohnny Chen                 {
697e9a5627eSJohnny Chen                     const WatchpointOptions *wp_options = wp->GetOptions();
698e9a5627eSJohnny Chen                     if (wp_options)
699e9a5627eSJohnny Chen                     {
700e9a5627eSJohnny Chen                         // Get the callback baton associated with the current watchpoint.
701e9a5627eSJohnny Chen                         const Baton *baton = wp_options->GetBaton();
702e9a5627eSJohnny Chen                         if (baton)
703e9a5627eSJohnny Chen                         {
704e9a5627eSJohnny Chen                             result.GetOutputStream().Printf ("Watchpoint %u:\n", cur_wp_id);
705e9a5627eSJohnny Chen                             result.GetOutputStream().IndentMore ();
706e9a5627eSJohnny Chen                             baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
707e9a5627eSJohnny Chen                             result.GetOutputStream().IndentLess ();
708e9a5627eSJohnny Chen                         }
709e9a5627eSJohnny Chen                         else
710e9a5627eSJohnny Chen                         {
711e9a5627eSJohnny Chen                             result.AppendMessageWithFormat ("Watchpoint %u does not have an associated command.\n",
712e9a5627eSJohnny Chen                                                             cur_wp_id);
713e9a5627eSJohnny Chen                         }
714e9a5627eSJohnny Chen                     }
715e9a5627eSJohnny Chen                     result.SetStatus (eReturnStatusSuccessFinishResult);
716e9a5627eSJohnny Chen                 }
717e9a5627eSJohnny Chen                 else
718e9a5627eSJohnny Chen                 {
719e9a5627eSJohnny Chen                     result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n", cur_wp_id);
720e9a5627eSJohnny Chen                     result.SetStatus (eReturnStatusFailed);
721e9a5627eSJohnny Chen                 }
722e9a5627eSJohnny Chen             }
723e9a5627eSJohnny Chen         }
724e9a5627eSJohnny Chen 
725e9a5627eSJohnny Chen         return result.Succeeded();
726e9a5627eSJohnny Chen     }
727e9a5627eSJohnny Chen };
728e9a5627eSJohnny Chen 
729e9a5627eSJohnny Chen //-------------------------------------------------------------------------
730e9a5627eSJohnny Chen // CommandObjectWatchpointCommand
731e9a5627eSJohnny Chen //-------------------------------------------------------------------------
732e9a5627eSJohnny Chen 
733e9a5627eSJohnny Chen CommandObjectWatchpointCommand::CommandObjectWatchpointCommand (CommandInterpreter &interpreter) :
734e9a5627eSJohnny Chen     CommandObjectMultiword (interpreter,
735e9a5627eSJohnny Chen                             "command",
736e9a5627eSJohnny Chen                             "A set of commands for adding, removing and examining bits of code to be executed when the watchpoint is hit (watchpoint 'commmands').",
737e9a5627eSJohnny Chen                             "command <sub-command> [<sub-command-options>] <watchpoint-id>")
738e9a5627eSJohnny Chen {
739e9a5627eSJohnny Chen     CommandObjectSP add_command_object (new CommandObjectWatchpointCommandAdd (interpreter));
740e9a5627eSJohnny Chen     CommandObjectSP delete_command_object (new CommandObjectWatchpointCommandDelete (interpreter));
741e9a5627eSJohnny Chen     CommandObjectSP list_command_object (new CommandObjectWatchpointCommandList (interpreter));
742e9a5627eSJohnny Chen 
743e9a5627eSJohnny Chen     add_command_object->SetCommandName ("watchpoint command add");
744e9a5627eSJohnny Chen     delete_command_object->SetCommandName ("watchpoint command delete");
745e9a5627eSJohnny Chen     list_command_object->SetCommandName ("watchpoint command list");
746e9a5627eSJohnny Chen 
74703da4cc2SGreg Clayton     LoadSubCommand ("add",    add_command_object);
74803da4cc2SGreg Clayton     LoadSubCommand ("delete", delete_command_object);
74903da4cc2SGreg Clayton     LoadSubCommand ("list",   list_command_object);
750e9a5627eSJohnny Chen }
751e9a5627eSJohnny Chen 
752e9a5627eSJohnny Chen CommandObjectWatchpointCommand::~CommandObjectWatchpointCommand ()
753e9a5627eSJohnny Chen {
754e9a5627eSJohnny Chen }
755e9a5627eSJohnny Chen 
756e9a5627eSJohnny Chen 
757