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