blob: 123a5ade06131066b2064c27e847b8dc037ad2ff [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 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000247 const size_t count = valid_bp_ids.GetSize();
248 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000249 {
250 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
251 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
252 {
253 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
254 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
255 {
256 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
257 if (bp_loc_sp)
258 {
259 if (m_options.m_use_script_language)
260 {
Greg Clayton63094e02010-06-23 01:19:29 +0000261 interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_loc_sp->GetLocationOptions(),
Chris Lattner24943d22010-06-08 16:52:24 +0000262 result);
263 }
264 else
265 {
Greg Clayton63094e02010-06-23 01:19:29 +0000266 CollectDataForBreakpointCommandCallback (interpreter, bp_loc_sp->GetLocationOptions(), result);
Chris Lattner24943d22010-06-08 16:52:24 +0000267 }
268 }
269 }
270 else
271 {
272 if (m_options.m_use_script_language)
273 {
Greg Clayton63094e02010-06-23 01:19:29 +0000274 interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp->GetOptions(),
Chris Lattner24943d22010-06-08 16:52:24 +0000275 result);
276 }
277 else
278 {
Greg Clayton63094e02010-06-23 01:19:29 +0000279 CollectDataForBreakpointCommandCallback (interpreter, bp->GetOptions(), result);
Chris Lattner24943d22010-06-08 16:52:24 +0000280 }
281 }
282 }
283 }
284 }
285
286 return result.Succeeded();
287}
288
289Options *
290CommandObjectBreakpointCommandAdd::GetOptions ()
291{
292 return &m_options;
293}
294
295const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
296
297void
298CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
299(
Greg Clayton63094e02010-06-23 01:19:29 +0000300 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000301 BreakpointOptions *bp_options,
302 CommandReturnObject &result
303)
304{
Greg Clayton63094e02010-06-23 01:19:29 +0000305 InputReaderSP reader_sp (new InputReader(interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000306 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
307 if (reader_sp && data_ap.get())
308 {
309 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
310 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
311
312 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
313 bp_options, // baton
314 eInputReaderGranularityLine, // token size, to pass to callback function
315 "DONE", // end token
316 "> ", // prompt
317 true)); // echo input
318 if (err.Success())
319 {
Greg Clayton63094e02010-06-23 01:19:29 +0000320 interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000321 result.SetStatus (eReturnStatusSuccessFinishNoResult);
322 }
323 else
324 {
325 result.AppendError (err.AsCString());
326 result.SetStatus (eReturnStatusFailed);
327 }
328 }
329 else
330 {
331 result.AppendError("out of memory");
332 result.SetStatus (eReturnStatusFailed);
333 }
334
335}
336
337size_t
338CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
339(
340 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000341 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000342 lldb::InputReaderAction notification,
343 const char *bytes,
344 size_t bytes_len
345)
346{
Greg Clayton63094e02010-06-23 01:19:29 +0000347 FILE *out_fh = reader.GetDebugger().GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000348
349 switch (notification)
350 {
351 case eInputReaderActivate:
352 if (out_fh)
353 {
354 ::fprintf (out_fh, "%s\n", g_reader_instructions);
Greg Clayton63094e02010-06-23 01:19:29 +0000355 if (reader.GetPrompt())
356 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000357 }
358 break;
359
360 case eInputReaderDeactivate:
361 break;
362
363 case eInputReaderReactivate:
Greg Clayton63094e02010-06-23 01:19:29 +0000364 if (out_fh && reader.GetPrompt())
365 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000366 break;
367
368 case eInputReaderGotToken:
369 if (bytes && bytes_len && baton)
370 {
371 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
372 if (bp_options)
373 {
374 Baton *bp_options_baton = bp_options->GetBaton();
375 if (bp_options_baton)
376 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
377 }
378 }
Greg Clayton63094e02010-06-23 01:19:29 +0000379 if (out_fh && !reader.IsDone() && reader.GetPrompt())
380 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000381 break;
382
383 case eInputReaderDone:
384 break;
385 }
386
387 return bytes_len;
388}
389
390
391//-------------------------------------------------------------------------
392// CommandObjectBreakpointCommandRemove
393//-------------------------------------------------------------------------
394
395CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove () :
396 CommandObject ("remove",
397 "Remove the set of commands from a breakpoint.",
398 "breakpoint command remove <breakpoint-id>")
399{
400}
401
402CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
403{
404}
405
406bool
Greg Clayton63094e02010-06-23 01:19:29 +0000407CommandObjectBreakpointCommandRemove::Execute
408(
409 CommandInterpreter &interpreter,
410 Args& command,
411 CommandReturnObject &result
412)
Chris Lattner24943d22010-06-08 16:52:24 +0000413{
Greg Clayton63094e02010-06-23 01:19:29 +0000414 Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000415
416 if (target == NULL)
417 {
418 result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands");
419 result.SetStatus (eReturnStatusFailed);
420 return false;
421 }
422
423 const BreakpointList &breakpoints = target->GetBreakpointList();
424 size_t num_breakpoints = breakpoints.GetSize();
425
426 if (num_breakpoints == 0)
427 {
428 result.AppendError ("No breakpoints exist to have commands removed");
429 result.SetStatus (eReturnStatusFailed);
430 return false;
431 }
432
433 if (command.GetArgumentCount() == 0)
434 {
435 result.AppendError ("No breakpoint specified from which to remove the commands");
436 result.SetStatus (eReturnStatusFailed);
437 return false;
438 }
439
440 BreakpointIDList valid_bp_ids;
441 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
442
443 if (result.Succeeded())
444 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000445 const size_t count = valid_bp_ids.GetSize();
446 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000447 {
448 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
449 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
450 {
451 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
452 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
453 {
454 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
455 if (bp_loc_sp)
456 bp_loc_sp->ClearCallback();
457 else
458 {
459 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
460 cur_bp_id.GetBreakpointID(),
461 cur_bp_id.GetLocationID());
462 result.SetStatus (eReturnStatusFailed);
463 return false;
464 }
465 }
466 else
467 {
468 bp->ClearCallback();
469 }
470 }
471 }
472 }
473 return result.Succeeded();
474}
475
476
477//-------------------------------------------------------------------------
478// CommandObjectBreakpointCommandList
479//-------------------------------------------------------------------------
480
481CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList () :
482 CommandObject ("List",
483 "List the script or set of commands to be executed when the breakpoint is hit.",
484 "breakpoint command list <breakpoint-id>")
485{
486}
487
488CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
489{
490}
491
492bool
Greg Clayton63094e02010-06-23 01:19:29 +0000493CommandObjectBreakpointCommandList::Execute
494(
495 CommandInterpreter &interpreter,
496 Args& command,
497 CommandReturnObject &result
498)
Chris Lattner24943d22010-06-08 16:52:24 +0000499{
Greg Clayton63094e02010-06-23 01:19:29 +0000500 Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000501
502 if (target == NULL)
503 {
504 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
505 result.SetStatus (eReturnStatusFailed);
506 return false;
507 }
508
509 const BreakpointList &breakpoints = target->GetBreakpointList();
510 size_t num_breakpoints = breakpoints.GetSize();
511
512 if (num_breakpoints == 0)
513 {
514 result.AppendError ("No breakpoints exist for which to list commands");
515 result.SetStatus (eReturnStatusFailed);
516 return false;
517 }
518
519 if (command.GetArgumentCount() == 0)
520 {
521 result.AppendError ("No breakpoint specified for which to list the commands");
522 result.SetStatus (eReturnStatusFailed);
523 return false;
524 }
525
526 BreakpointIDList valid_bp_ids;
527 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
528
529 if (result.Succeeded())
530 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000531 const size_t count = valid_bp_ids.GetSize();
532 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000533 {
534 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
535 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
536 {
537 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
538
539 if (bp)
540 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000541 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000542 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
543 {
544 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
545 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000546 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000547 else
548 {
549 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
550 cur_bp_id.GetBreakpointID(),
551 cur_bp_id.GetLocationID());
552 result.SetStatus (eReturnStatusFailed);
553 return false;
554 }
555 }
556 else
557 {
558 bp_options = bp->GetOptions();
559 }
560
561 if (bp_options)
562 {
563 StreamString id_str;
564 BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000565 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000566 if (baton)
567 {
568 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
569 result.GetOutputStream().IndentMore ();
570 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
571 result.GetOutputStream().IndentLess ();
572 }
573 else
574 {
575 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", id_str.GetData());
576 }
577 }
578 result.SetStatus (eReturnStatusSuccessFinishResult);
579 }
580 else
581 {
582 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
583 result.SetStatus (eReturnStatusFailed);
584 }
585
586 }
587 }
588 }
589
590 return result.Succeeded();
591}
592
593//-------------------------------------------------------------------------
594// CommandObjectBreakpointCommand
595//-------------------------------------------------------------------------
596
Greg Clayton63094e02010-06-23 01:19:29 +0000597CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +0000598 CommandObjectMultiword ("command",
599 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
600 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
601{
602 bool status;
603 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd ());
604 CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove ());
605 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList ());
606
607 add_command_object->SetCommandName ("breakpoint command add");
608 remove_command_object->SetCommandName ("breakpoint command remove");
609 list_command_object->SetCommandName ("breakpoint command list");
610
Greg Clayton63094e02010-06-23 01:19:29 +0000611 status = LoadSubCommand (interpreter, "add", add_command_object);
612 status = LoadSubCommand (interpreter, "remove", remove_command_object);
613 status = LoadSubCommand (interpreter, "list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000614}
615
616
617CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
618{
619}
620
621bool
622CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
623(
624 void *baton,
625 StoppointCallbackContext *context,
626 lldb::user_id_t break_id,
627 lldb::user_id_t break_loc_id
628)
629{
630 bool ret_value = true;
631 if (baton == NULL)
632 return true;
633
634
635 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
636 StringList &commands = data->user_source;
637
638 if (commands.GetSize() > 0)
639 {
640 uint32_t num_commands = commands.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000641 CommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000642 if (context->exe_ctx.target)
Chris Lattner24943d22010-06-08 16:52:24 +0000643 {
Greg Clayton63094e02010-06-23 01:19:29 +0000644
645 Debugger &debugger = context->exe_ctx.target->GetDebugger();
646 CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
647
648 FILE *out_fh = debugger.GetOutputFileHandle();
649 FILE *err_fh = debugger.GetErrorFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000650
Greg Clayton63094e02010-06-23 01:19:29 +0000651 uint32_t i;
652 for (i = 0; i < num_commands; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000653 {
Greg Clayton63094e02010-06-23 01:19:29 +0000654
655 // First time through we use the context from the stoppoint, after that we use whatever
656 // has been set by the previous command.
657
658 if (!interpreter.HandleCommand (commands.GetStringAtIndex(i), false, result, &context->exe_ctx))
659 break;
660
661 // FIXME: This isn't really the right way to do this. We should be able to peek at the public
662 // to see if there is any new events, but that is racey, since the internal process thread has to run and
663 // deliver the event to the public queue before a run will show up. So for now we check
664 // the internal thread state.
665
666 lldb::StateType internal_state = context->exe_ctx.process->GetPrivateState();
667 if (internal_state != eStateStopped)
Chris Lattner24943d22010-06-08 16:52:24 +0000668 {
Greg Clayton63094e02010-06-23 01:19:29 +0000669 if (i < num_commands - 1)
670 {
671 if (out_fh)
672 ::fprintf (out_fh, "Short-circuiting command execution because target state changed to %s."
673 " last command: \"%s\"\n", StateAsCString(internal_state),
674 commands.GetStringAtIndex(i));
675 }
676 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000677 }
Greg Clayton63094e02010-06-23 01:19:29 +0000678
679 if (out_fh)
680 ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
681 if (err_fh)
682 ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
683 result.Clear();
684 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000685 }
Chris Lattner24943d22010-06-08 16:52:24 +0000686
Greg Clayton63094e02010-06-23 01:19:29 +0000687 if (err_fh && !result.Succeeded() && i < num_commands)
688 ::fprintf (err_fh, "Attempt to execute '%s' failed.\n", commands.GetStringAtIndex(i));
689
Chris Lattner24943d22010-06-08 16:52:24 +0000690 if (out_fh)
691 ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
Greg Clayton63094e02010-06-23 01:19:29 +0000692
Chris Lattner24943d22010-06-08 16:52:24 +0000693 if (err_fh)
Greg Clayton63094e02010-06-23 01:19:29 +0000694 ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000695 }
Chris Lattner24943d22010-06-08 16:52:24 +0000696 }
697 return ret_value;
698}
699