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