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