blob: 547192dc68a6a24935b107cb918d21eac85ca234 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
11// C++ Includes
12
13
14#include "CommandObjectBreakpointCommand.h"
15#include "CommandObjectBreakpoint.h"
16
17#include "lldb/Interpreter/CommandInterpreter.h"
18#include "lldb/Interpreter/CommandReturnObject.h"
19#include "lldb/Target/Target.h"
20#include "lldb/Target/Thread.h"
21#include "lldb/Breakpoint/BreakpointIDList.h"
22#include "lldb/Breakpoint/Breakpoint.h"
23#include "lldb/Breakpoint/BreakpointLocation.h"
24#include "lldb/Breakpoint/StoppointCallbackContext.h"
25#include "lldb/Core/State.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30//-------------------------------------------------------------------------
31// CommandObjectBreakpointCommandAdd::CommandOptions
32//-------------------------------------------------------------------------
33
34CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions () :
35 Options ()
36{
Chris Lattner24943d22010-06-08 16:52:24 +000037}
38
39CommandObjectBreakpointCommandAdd::CommandOptions::~CommandOptions ()
40{
41}
42
43lldb::OptionDefinition
44CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
45{
Jim Ingham34e9a982010-06-15 18:47:14 +000046 { LLDB_OPT_SET_1, true, "script", 's', no_argument, NULL, 0, NULL,
Chris Lattner24943d22010-06-08 16:52:24 +000047 "Write the breakpoint command script in the default scripting language."},
48
Jim Ingham34e9a982010-06-15 18:47:14 +000049 { LLDB_OPT_SET_2, true, "python", 'p', no_argument, NULL, 0, NULL,
Chris Lattner24943d22010-06-08 16:52:24 +000050 "Write the breakpoint command script in the Python scripting language."},
51
Jim Ingham34e9a982010-06-15 18:47:14 +000052 { LLDB_OPT_SET_3, true, "commands", 'c', no_argument, NULL, 0, NULL,
Chris Lattner24943d22010-06-08 16:52:24 +000053 "Write the breakpoint command script using the command line commands."},
54
55 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
56};
57
58const lldb::OptionDefinition*
59CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions ()
60{
61 return g_option_table;
62}
63
64
65Error
66CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
67(
68 int option_idx,
69 const char *option_arg
70)
71{
72 Error error;
73 char short_option = (char) m_getopt_table[option_idx].val;
74
75 switch (short_option)
76 {
77 case 's':
78 m_use_commands = false;
79 m_use_script_language = true;
80 m_script_language = eScriptLanguageDefault;
81 break;
82 case 'p':
83 m_use_commands = false;
84 m_use_script_language = true;
85 m_script_language = eScriptLanguagePython;
86 break;
87 case 'c':
88 m_use_commands = true;
89 m_use_script_language = false;
90 m_script_language = eScriptLanguageNone;
91 break;
92 default:
93 break;
94 }
95 return error;
96}
97
98void
99CommandObjectBreakpointCommandAdd::CommandOptions::ResetOptionValues ()
100{
101 Options::ResetOptionValues();
102
103 m_use_commands = false;
104 m_use_script_language = false;
105 m_script_language = eScriptLanguageNone;
106}
107
108//-------------------------------------------------------------------------
109// CommandObjectBreakpointCommandAdd
110//-------------------------------------------------------------------------
111
112
113CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd () :
114 CommandObject ("add",
115 "Adds a set of commands to a breakpoint to be executed whenever a breakpoint is hit.",
116 "breakpoint command add <cmd-options> <breakpoint-id>")
117{
118 SetHelpLong (
119"\nGeneral information about entering breakpoint commands \n\
120------------------------------------------------------ \n\
121 \n\
122This command will cause you to be prompted to enter the command or set \n\
123of commands you wish to be executed when the specified breakpoint is \n\
124hit. You will be told to enter your command(s), and will see a '> ' \n\
125prompt. Because you can enter one or many commands to be executed when \n\
126a breakpoint is hit, you will continue to be prompted after each \n\
127new-line that you enter, until you enter the word 'DONE', which will \n\
128cause the commands you have entered to be stored with the breakpoint \n\
129and executed when the breakpoint is hit. \n\
130 \n\
131Syntax checking is not necessarily done when breakpoint commands are \n\
132entered. An improperly written breakpoint command will attempt to get \n\
133executed when the breakpoint gets hit, and usually silently fail. If \n\
134your breakpoint command does not appear to be getting executed, go \n\
135back and check your syntax. \n\
136 \n\
137 \n\
138Special information about PYTHON breakpoint commands \n\
139---------------------------------------------------- \n\
140 \n\
141You may enter either one line of Python or multiple lines of Python \n\
142(including defining whole functions, if desired). If you enter a \n\
143single line of Python, that will be passed to the Python interpreter \n\
144'as is' when the breakpoint gets hit. If you enter function \n\
145definitions, they will be passed to the Python interpreter as soon as \n\
146you finish entering the breakpoint command, and they can be called \n\
147later (don't forget to add calls to them, if you want them called when \n\
148the breakpoint is hit). If you enter multiple lines of Python that \n\
149are not function definitions, they will be collected into a new, \n\
150automatically generated Python function, and a call to the newly \n\
151generated function will be attached to the breakpoint. Important \n\
152Note: Because loose Python code gets collected into functions, if you \n\
153want to access global variables in the 'loose' code, you need to \n\
154specify that they are global, using the 'global' keyword. Be sure to \n\
155use correct Python syntax, including indentation, when entering Python \n\
156breakpoint commands. \n\
157 \n\
158Example Python one-line breakpoint command: \n\
159 \n\
160(lldb) breakpoint command add -p 1 \n\
161Enter your Python command(s). Type 'DONE' to end. \n\
162> print \"Hit this breakpoint!\" \n\
163> DONE \n\
164 \n\
165Example multiple line Python breakpoint command, using function definition: \n\
166 \n\
167(lldb) breakpoint command add -p 1 \n\
168Enter your Python command(s). Type 'DONE' to end. \n\
169> def breakpoint_output (bp_no): \n\
170> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
171> print out_string \n\
172> return True \n\
173> breakpoint_output (1) \n\
174> DONE \n\
175 \n\
176 \n\
177Example multiple line Python breakpoint command, using 'loose' Python: \n\
178 \n\
179(lldb) breakpoint command add -p 1 \n\
180Enter your Python command(s). Type 'DONE' to end. \n\
181> global bp_count \n\
182> bp_count = bp_count + 1 \n\
183> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
184> DONE \n\
185 \n\
186In this case, since there is a reference to a global variable, \n\
187'bp_count', you will also need to make sure 'bp_count' exists and is \n\
188initialized: \n\
189 \n\
190(lldb) script \n\
191>>> bp_count = 0 \n\
192>>> quit() \n\
193 \n\
194(lldb) \n\
195 \n\
196Special information debugger command breakpoint commands \n\
197--------------------------------------------------------- \n\
198 \n\
199You may enter any debugger command, exactly as you would at the \n\
200debugger prompt. You may enter as many debugger commands as you like, \n\
201but do NOT enter more than one command per line. \n" );
202}
203
204CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
205{
206}
207
208bool
209CommandObjectBreakpointCommandAdd::Execute
210(
Greg Clayton63094e02010-06-23 01:19:29 +0000211 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000212 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000213 CommandReturnObject &result
214)
215{
Greg Clayton63094e02010-06-23 01:19:29 +0000216 Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000217
218 if (target == NULL)
219 {
220 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
221 result.SetStatus (eReturnStatusFailed);
222 return false;
223 }
224
225 const BreakpointList &breakpoints = target->GetBreakpointList();
226 size_t num_breakpoints = breakpoints.GetSize();
227
228 if (num_breakpoints == 0)
229 {
230 result.AppendError ("No breakpoints exist to have commands added");
231 result.SetStatus (eReturnStatusFailed);
232 return false;
233 }
234
235 if (command.GetArgumentCount() == 0)
236 {
237 result.AppendError ("No breakpoint specified to which to add the commands");
238 result.SetStatus (eReturnStatusFailed);
239 return false;
240 }
241
242 BreakpointIDList valid_bp_ids;
243 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
244
245 if (result.Succeeded())
246 {
247 for (int i = 0; i < valid_bp_ids.Size(); ++i)
248 {
249 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
250 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
251 {
252 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
253 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
254 {
255 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
256 if (bp_loc_sp)
257 {
258 if (m_options.m_use_script_language)
259 {
Greg Clayton63094e02010-06-23 01:19:29 +0000260 interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_loc_sp->GetLocationOptions(),
Chris Lattner24943d22010-06-08 16:52:24 +0000261 result);
262 }
263 else
264 {
Greg Clayton63094e02010-06-23 01:19:29 +0000265 CollectDataForBreakpointCommandCallback (interpreter, bp_loc_sp->GetLocationOptions(), result);
Chris Lattner24943d22010-06-08 16:52:24 +0000266 }
267 }
268 }
269 else
270 {
271 if (m_options.m_use_script_language)
272 {
Greg Clayton63094e02010-06-23 01:19:29 +0000273 interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp->GetOptions(),
Chris Lattner24943d22010-06-08 16:52:24 +0000274 result);
275 }
276 else
277 {
Greg Clayton63094e02010-06-23 01:19:29 +0000278 CollectDataForBreakpointCommandCallback (interpreter, bp->GetOptions(), result);
Chris Lattner24943d22010-06-08 16:52:24 +0000279 }
280 }
281 }
282 }
283 }
284
285 return result.Succeeded();
286}
287
288Options *
289CommandObjectBreakpointCommandAdd::GetOptions ()
290{
291 return &m_options;
292}
293
294const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
295
296void
297CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
298(
Greg Clayton63094e02010-06-23 01:19:29 +0000299 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000300 BreakpointOptions *bp_options,
301 CommandReturnObject &result
302)
303{
Greg Clayton63094e02010-06-23 01:19:29 +0000304 InputReaderSP reader_sp (new InputReader(interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000305 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
306 if (reader_sp && data_ap.get())
307 {
308 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
309 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
310
311 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
312 bp_options, // baton
313 eInputReaderGranularityLine, // token size, to pass to callback function
314 "DONE", // end token
315 "> ", // prompt
316 true)); // echo input
317 if (err.Success())
318 {
Greg Clayton63094e02010-06-23 01:19:29 +0000319 interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000320 result.SetStatus (eReturnStatusSuccessFinishNoResult);
321 }
322 else
323 {
324 result.AppendError (err.AsCString());
325 result.SetStatus (eReturnStatusFailed);
326 }
327 }
328 else
329 {
330 result.AppendError("out of memory");
331 result.SetStatus (eReturnStatusFailed);
332 }
333
334}
335
336size_t
337CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
338(
339 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000340 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000341 lldb::InputReaderAction notification,
342 const char *bytes,
343 size_t bytes_len
344)
345{
Greg Clayton63094e02010-06-23 01:19:29 +0000346 FILE *out_fh = reader.GetDebugger().GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000347
348 switch (notification)
349 {
350 case eInputReaderActivate:
351 if (out_fh)
352 {
353 ::fprintf (out_fh, "%s\n", g_reader_instructions);
Greg Clayton63094e02010-06-23 01:19:29 +0000354 if (reader.GetPrompt())
355 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000356 }
357 break;
358
359 case eInputReaderDeactivate:
360 break;
361
362 case eInputReaderReactivate:
Greg Clayton63094e02010-06-23 01:19:29 +0000363 if (out_fh && reader.GetPrompt())
364 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000365 break;
366
367 case eInputReaderGotToken:
368 if (bytes && bytes_len && baton)
369 {
370 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
371 if (bp_options)
372 {
373 Baton *bp_options_baton = bp_options->GetBaton();
374 if (bp_options_baton)
375 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
376 }
377 }
Greg Clayton63094e02010-06-23 01:19:29 +0000378 if (out_fh && !reader.IsDone() && reader.GetPrompt())
379 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000380 break;
381
382 case eInputReaderDone:
383 break;
384 }
385
386 return bytes_len;
387}
388
389
390//-------------------------------------------------------------------------
391// CommandObjectBreakpointCommandRemove
392//-------------------------------------------------------------------------
393
394CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove () :
395 CommandObject ("remove",
396 "Remove the set of commands from a breakpoint.",
397 "breakpoint command remove <breakpoint-id>")
398{
399}
400
401CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
402{
403}
404
405bool
Greg Clayton63094e02010-06-23 01:19:29 +0000406CommandObjectBreakpointCommandRemove::Execute
407(
408 CommandInterpreter &interpreter,
409 Args& command,
410 CommandReturnObject &result
411)
Chris Lattner24943d22010-06-08 16:52:24 +0000412{
Greg Clayton63094e02010-06-23 01:19:29 +0000413 Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000414
415 if (target == NULL)
416 {
417 result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands");
418 result.SetStatus (eReturnStatusFailed);
419 return false;
420 }
421
422 const BreakpointList &breakpoints = target->GetBreakpointList();
423 size_t num_breakpoints = breakpoints.GetSize();
424
425 if (num_breakpoints == 0)
426 {
427 result.AppendError ("No breakpoints exist to have commands removed");
428 result.SetStatus (eReturnStatusFailed);
429 return false;
430 }
431
432 if (command.GetArgumentCount() == 0)
433 {
434 result.AppendError ("No breakpoint specified from which to remove the commands");
435 result.SetStatus (eReturnStatusFailed);
436 return false;
437 }
438
439 BreakpointIDList valid_bp_ids;
440 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
441
442 if (result.Succeeded())
443 {
444 for (int i = 0; i < valid_bp_ids.Size(); ++i)
445 {
446 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
447 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
448 {
449 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
450 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
451 {
452 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
453 if (bp_loc_sp)
454 bp_loc_sp->ClearCallback();
455 else
456 {
457 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
458 cur_bp_id.GetBreakpointID(),
459 cur_bp_id.GetLocationID());
460 result.SetStatus (eReturnStatusFailed);
461 return false;
462 }
463 }
464 else
465 {
466 bp->ClearCallback();
467 }
468 }
469 }
470 }
471 return result.Succeeded();
472}
473
474
475//-------------------------------------------------------------------------
476// CommandObjectBreakpointCommandList
477//-------------------------------------------------------------------------
478
479CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList () :
480 CommandObject ("List",
481 "List the script or set of commands to be executed when the breakpoint is hit.",
482 "breakpoint command list <breakpoint-id>")
483{
484}
485
486CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
487{
488}
489
490bool
Greg Clayton63094e02010-06-23 01:19:29 +0000491CommandObjectBreakpointCommandList::Execute
492(
493 CommandInterpreter &interpreter,
494 Args& command,
495 CommandReturnObject &result
496)
Chris Lattner24943d22010-06-08 16:52:24 +0000497{
Greg Clayton63094e02010-06-23 01:19:29 +0000498 Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000499
500 if (target == NULL)
501 {
502 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
503 result.SetStatus (eReturnStatusFailed);
504 return false;
505 }
506
507 const BreakpointList &breakpoints = target->GetBreakpointList();
508 size_t num_breakpoints = breakpoints.GetSize();
509
510 if (num_breakpoints == 0)
511 {
512 result.AppendError ("No breakpoints exist for which to list commands");
513 result.SetStatus (eReturnStatusFailed);
514 return false;
515 }
516
517 if (command.GetArgumentCount() == 0)
518 {
519 result.AppendError ("No breakpoint specified for which to list the commands");
520 result.SetStatus (eReturnStatusFailed);
521 return false;
522 }
523
524 BreakpointIDList valid_bp_ids;
525 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
526
527 if (result.Succeeded())
528 {
529 for (int i = 0; i < valid_bp_ids.Size(); ++i)
530 {
531 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
532 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
533 {
534 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
535
536 if (bp)
537 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000538 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000539 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
540 {
541 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
542 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000543 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000544 else
545 {
546 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
547 cur_bp_id.GetBreakpointID(),
548 cur_bp_id.GetLocationID());
549 result.SetStatus (eReturnStatusFailed);
550 return false;
551 }
552 }
553 else
554 {
555 bp_options = bp->GetOptions();
556 }
557
558 if (bp_options)
559 {
560 StreamString id_str;
561 BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000562 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000563 if (baton)
564 {
565 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
566 result.GetOutputStream().IndentMore ();
567 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
568 result.GetOutputStream().IndentLess ();
569 }
570 else
571 {
572 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", id_str.GetData());
573 }
574 }
575 result.SetStatus (eReturnStatusSuccessFinishResult);
576 }
577 else
578 {
579 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
580 result.SetStatus (eReturnStatusFailed);
581 }
582
583 }
584 }
585 }
586
587 return result.Succeeded();
588}
589
590//-------------------------------------------------------------------------
591// CommandObjectBreakpointCommand
592//-------------------------------------------------------------------------
593
Greg Clayton63094e02010-06-23 01:19:29 +0000594CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +0000595 CommandObjectMultiword ("command",
596 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
597 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
598{
599 bool status;
600 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd ());
601 CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove ());
602 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList ());
603
604 add_command_object->SetCommandName ("breakpoint command add");
605 remove_command_object->SetCommandName ("breakpoint command remove");
606 list_command_object->SetCommandName ("breakpoint command list");
607
Greg Clayton63094e02010-06-23 01:19:29 +0000608 status = LoadSubCommand (interpreter, "add", add_command_object);
609 status = LoadSubCommand (interpreter, "remove", remove_command_object);
610 status = LoadSubCommand (interpreter, "list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000611}
612
613
614CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
615{
616}
617
618bool
619CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
620(
621 void *baton,
622 StoppointCallbackContext *context,
623 lldb::user_id_t break_id,
624 lldb::user_id_t break_loc_id
625)
626{
627 bool ret_value = true;
628 if (baton == NULL)
629 return true;
630
631
632 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
633 StringList &commands = data->user_source;
634
635 if (commands.GetSize() > 0)
636 {
637 uint32_t num_commands = commands.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000638 CommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000639 if (context->exe_ctx.target)
Chris Lattner24943d22010-06-08 16:52:24 +0000640 {
Greg Clayton63094e02010-06-23 01:19:29 +0000641
642 Debugger &debugger = context->exe_ctx.target->GetDebugger();
643 CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
644
645 FILE *out_fh = debugger.GetOutputFileHandle();
646 FILE *err_fh = debugger.GetErrorFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000647
Greg Clayton63094e02010-06-23 01:19:29 +0000648 uint32_t i;
649 for (i = 0; i < num_commands; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000650 {
Greg Clayton63094e02010-06-23 01:19:29 +0000651
652 // First time through we use the context from the stoppoint, after that we use whatever
653 // has been set by the previous command.
654
655 if (!interpreter.HandleCommand (commands.GetStringAtIndex(i), false, result, &context->exe_ctx))
656 break;
657
658 // FIXME: This isn't really the right way to do this. We should be able to peek at the public
659 // to see if there is any new events, but that is racey, since the internal process thread has to run and
660 // deliver the event to the public queue before a run will show up. So for now we check
661 // the internal thread state.
662
663 lldb::StateType internal_state = context->exe_ctx.process->GetPrivateState();
664 if (internal_state != eStateStopped)
Chris Lattner24943d22010-06-08 16:52:24 +0000665 {
Greg Clayton63094e02010-06-23 01:19:29 +0000666 if (i < num_commands - 1)
667 {
668 if (out_fh)
669 ::fprintf (out_fh, "Short-circuiting command execution because target state changed to %s."
670 " last command: \"%s\"\n", StateAsCString(internal_state),
671 commands.GetStringAtIndex(i));
672 }
673 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000674 }
Greg Clayton63094e02010-06-23 01:19:29 +0000675
676 if (out_fh)
677 ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
678 if (err_fh)
679 ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
680 result.Clear();
681 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000682 }
Chris Lattner24943d22010-06-08 16:52:24 +0000683
Greg Clayton63094e02010-06-23 01:19:29 +0000684 if (err_fh && !result.Succeeded() && i < num_commands)
685 ::fprintf (err_fh, "Attempt to execute '%s' failed.\n", commands.GetStringAtIndex(i));
686
Chris Lattner24943d22010-06-08 16:52:24 +0000687 if (out_fh)
688 ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
Greg Clayton63094e02010-06-23 01:19:29 +0000689
Chris Lattner24943d22010-06-08 16:52:24 +0000690 if (err_fh)
Greg Clayton63094e02010-06-23 01:19:29 +0000691 ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000692 }
Chris Lattner24943d22010-06-08 16:52:24 +0000693 }
694 return ret_value;
695}
696