]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp
Merge lldb release_80 branch r351543, and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Breakpoint / BreakpointOptions.cpp
1 //===-- BreakpointOptions.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 #include "lldb/Breakpoint/BreakpointOptions.h"
11
12 #include "lldb/Breakpoint/StoppointCallbackContext.h"
13 #include "lldb/Core/Value.h"
14 #include "lldb/Interpreter/CommandInterpreter.h"
15 #include "lldb/Interpreter/CommandReturnObject.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Target/Target.h"
18 #include "lldb/Target/ThreadSpec.h"
19 #include "lldb/Utility/Stream.h"
20 #include "lldb/Utility/StringList.h"
21
22 #include "llvm/ADT/STLExtras.h"
23
24 using namespace lldb;
25 using namespace lldb_private;
26
27 const char
28     *BreakpointOptions::CommandData::g_option_names[static_cast<uint32_t>(
29         BreakpointOptions::CommandData::OptionNames::LastOptionName)]{
30         "UserSource", "ScriptSource", "StopOnError"};
31
32 StructuredData::ObjectSP
33 BreakpointOptions::CommandData::SerializeToStructuredData() {
34   size_t num_strings = user_source.GetSize();
35   if (num_strings == 0 && script_source.empty()) {
36     // We shouldn't serialize commands if there aren't any, return an empty sp
37     // to indicate this.
38     return StructuredData::ObjectSP();
39   }
40
41   StructuredData::DictionarySP options_dict_sp(
42       new StructuredData::Dictionary());
43   options_dict_sp->AddBooleanItem(GetKey(OptionNames::StopOnError),
44                                   stop_on_error);
45
46   StructuredData::ArraySP user_source_sp(new StructuredData::Array());
47   for (size_t i = 0; i < num_strings; i++) {
48     StructuredData::StringSP item_sp(
49         new StructuredData::String(user_source[i]));
50     user_source_sp->AddItem(item_sp);
51     options_dict_sp->AddItem(GetKey(OptionNames::UserSource), user_source_sp);
52   }
53
54   options_dict_sp->AddStringItem(
55       GetKey(OptionNames::Interpreter),
56       ScriptInterpreter::LanguageToString(interpreter));
57   return options_dict_sp;
58 }
59
60 std::unique_ptr<BreakpointOptions::CommandData>
61 BreakpointOptions::CommandData::CreateFromStructuredData(
62     const StructuredData::Dictionary &options_dict, Status &error) {
63   std::unique_ptr<CommandData> data_up(new CommandData());
64   bool found_something = false;
65
66   bool success = options_dict.GetValueForKeyAsBoolean(
67       GetKey(OptionNames::StopOnError), data_up->stop_on_error);
68
69   if (success)
70     found_something = true;
71
72   llvm::StringRef interpreter_str;
73   ScriptLanguage interp_language;
74   success = options_dict.GetValueForKeyAsString(
75       GetKey(OptionNames::Interpreter), interpreter_str);
76
77   if (!success) {
78     error.SetErrorString("Missing command language value.");
79     return data_up;
80   }
81
82   found_something = true;
83   interp_language = ScriptInterpreter::StringToLanguage(interpreter_str);
84   if (interp_language == eScriptLanguageUnknown) {
85     error.SetErrorStringWithFormatv("Unknown breakpoint command language: {0}.",
86                                     interpreter_str);
87     return data_up;
88   }
89   data_up->interpreter = interp_language;
90
91   StructuredData::Array *user_source;
92   success = options_dict.GetValueForKeyAsArray(GetKey(OptionNames::UserSource),
93                                                user_source);
94   if (success) {
95     found_something = true;
96     size_t num_elems = user_source->GetSize();
97     for (size_t i = 0; i < num_elems; i++) {
98       llvm::StringRef elem_string;
99       success = user_source->GetItemAtIndexAsString(i, elem_string);
100       if (success)
101         data_up->user_source.AppendString(elem_string);
102     }
103   }
104
105   if (found_something)
106     return data_up;
107   else
108     return std::unique_ptr<BreakpointOptions::CommandData>();
109 }
110
111 const char *BreakpointOptions::g_option_names[(
112     size_t)BreakpointOptions::OptionNames::LastOptionName]{
113     "ConditionText", "IgnoreCount", 
114     "EnabledState", "OneShotState", "AutoContinue"};
115
116 bool BreakpointOptions::NullCallback(void *baton,
117                                      StoppointCallbackContext *context,
118                                      lldb::user_id_t break_id,
119                                      lldb::user_id_t break_loc_id) {
120   return true;
121 }
122
123 //----------------------------------------------------------------------
124 // BreakpointOptions constructor
125 //----------------------------------------------------------------------
126 BreakpointOptions::BreakpointOptions(bool all_flags_set)
127     : m_callback(BreakpointOptions::NullCallback), m_callback_baton_sp(),
128       m_baton_is_command_baton(false), m_callback_is_synchronous(false),
129       m_enabled(true), m_one_shot(false), m_ignore_count(0), m_thread_spec_ap(),
130       m_condition_text(), m_condition_text_hash(0), m_auto_continue(false),
131       m_set_flags(0) {
132         if (all_flags_set)
133           m_set_flags.Set(~((Flags::ValueType) 0));
134       }
135
136 BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
137                                      int32_t ignore, bool one_shot, 
138                                      bool auto_continue)
139     : m_callback(nullptr), m_baton_is_command_baton(false),
140       m_callback_is_synchronous(false), m_enabled(enabled),
141       m_one_shot(one_shot), m_ignore_count(ignore),
142       m_condition_text_hash(0), m_auto_continue(auto_continue)
143 {
144     m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot 
145                    | eAutoContinue);
146     if (condition && *condition != '\0') {
147       SetCondition(condition);
148     }
149 }
150
151 //----------------------------------------------------------------------
152 // BreakpointOptions copy constructor
153 //----------------------------------------------------------------------
154 BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs)
155     : m_callback(rhs.m_callback), m_callback_baton_sp(rhs.m_callback_baton_sp),
156       m_baton_is_command_baton(rhs.m_baton_is_command_baton),
157       m_callback_is_synchronous(rhs.m_callback_is_synchronous),
158       m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot),
159       m_ignore_count(rhs.m_ignore_count), m_thread_spec_ap(),
160       m_auto_continue(rhs.m_auto_continue),
161       m_set_flags(rhs.m_set_flags) {
162   if (rhs.m_thread_spec_ap.get() != nullptr)
163     m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
164   m_condition_text = rhs.m_condition_text;
165   m_condition_text_hash = rhs.m_condition_text_hash;
166 }
167
168 //----------------------------------------------------------------------
169 // BreakpointOptions assignment operator
170 //----------------------------------------------------------------------
171 const BreakpointOptions &BreakpointOptions::
172 operator=(const BreakpointOptions &rhs) {
173   m_callback = rhs.m_callback;
174   m_callback_baton_sp = rhs.m_callback_baton_sp;
175   m_baton_is_command_baton = rhs.m_baton_is_command_baton;
176   m_callback_is_synchronous = rhs.m_callback_is_synchronous;
177   m_enabled = rhs.m_enabled;
178   m_one_shot = rhs.m_one_shot;
179   m_ignore_count = rhs.m_ignore_count;
180   if (rhs.m_thread_spec_ap.get() != nullptr)
181     m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
182   m_condition_text = rhs.m_condition_text;
183   m_condition_text_hash = rhs.m_condition_text_hash;
184   m_auto_continue = rhs.m_auto_continue;
185   m_set_flags = rhs.m_set_flags;
186   return *this;
187 }
188
189 void BreakpointOptions::CopyOverSetOptions(const BreakpointOptions &incoming)
190 {
191   if (incoming.m_set_flags.Test(eEnabled))
192   {
193     m_enabled = incoming.m_enabled;
194     m_set_flags.Set(eEnabled);
195   }
196   if (incoming.m_set_flags.Test(eOneShot))
197   {
198     m_one_shot = incoming.m_one_shot;
199     m_set_flags.Set(eOneShot);
200   }
201   if (incoming.m_set_flags.Test(eCallback))
202   {
203     m_callback = incoming.m_callback;
204     m_callback_baton_sp = incoming.m_callback_baton_sp;
205     m_callback_is_synchronous = incoming.m_callback_is_synchronous;
206     m_baton_is_command_baton = incoming.m_baton_is_command_baton;
207     m_set_flags.Set(eCallback);
208   }
209   if (incoming.m_set_flags.Test(eIgnoreCount))
210   {
211     m_ignore_count = incoming.m_ignore_count;
212     m_set_flags.Set(eIgnoreCount);
213   }
214   if (incoming.m_set_flags.Test(eCondition))
215   {
216     // If we're copying over an empty condition, mark it as unset.
217     if (incoming.m_condition_text.empty()) {
218       m_condition_text.clear();
219       m_condition_text_hash = 0;
220       m_set_flags.Clear(eCondition);
221     } else {
222       m_condition_text = incoming.m_condition_text;
223       m_condition_text_hash = incoming.m_condition_text_hash;
224       m_set_flags.Set(eCondition);
225     }
226   }
227   if (incoming.m_set_flags.Test(eAutoContinue))
228   {
229     m_auto_continue = incoming.m_auto_continue;
230     m_set_flags.Set(eAutoContinue);
231   }
232   if (incoming.m_set_flags.Test(eThreadSpec) && incoming.m_thread_spec_ap)
233   {
234     if (!m_thread_spec_ap)
235       m_thread_spec_ap.reset(new ThreadSpec(*incoming.m_thread_spec_ap.get()));
236     else
237       *m_thread_spec_ap.get() = *incoming.m_thread_spec_ap.get();
238     m_set_flags.Set(eThreadSpec);
239   }
240 }
241
242 //----------------------------------------------------------------------
243 // Destructor
244 //----------------------------------------------------------------------
245 BreakpointOptions::~BreakpointOptions() = default;
246
247 std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
248     Target &target, const StructuredData::Dictionary &options_dict,
249     Status &error) {
250   bool enabled = true;
251   bool one_shot = false;
252   bool auto_continue = false;
253   int32_t ignore_count = 0;
254   llvm::StringRef condition_ref("");
255   Flags set_options;
256
257   const char *key = GetKey(OptionNames::EnabledState);
258   bool success;
259   if (key) {
260     success = options_dict.GetValueForKeyAsBoolean(key, enabled);
261     if (!success) {
262       error.SetErrorStringWithFormat("%s key is not a boolean.",
263                                    GetKey(OptionNames::EnabledState));
264       return nullptr;
265     }
266     set_options.Set(eEnabled);
267   }
268
269   key = GetKey(OptionNames::OneShotState);
270   if (key) {
271     success = options_dict.GetValueForKeyAsBoolean(key, one_shot);
272     if (!success) {
273       error.SetErrorStringWithFormat("%s key is not a boolean.",
274                                      GetKey(OptionNames::OneShotState));
275       return nullptr;
276       }
277       set_options.Set(eOneShot);
278   }
279   
280   key = GetKey(OptionNames::AutoContinue);
281   if (key) {
282     success = options_dict.GetValueForKeyAsBoolean(key, auto_continue);
283     if (!success) {
284       error.SetErrorStringWithFormat("%s key is not a boolean.",
285                                      GetKey(OptionNames::AutoContinue));
286       return nullptr;
287       }
288       set_options.Set(eAutoContinue);
289   }
290   
291   key = GetKey(OptionNames::IgnoreCount);
292   if (key) {
293     success = options_dict.GetValueForKeyAsInteger(key, ignore_count);
294     if (!success) {
295       error.SetErrorStringWithFormat("%s key is not an integer.",
296                                      GetKey(OptionNames::IgnoreCount));
297       return nullptr;
298     }
299     set_options.Set(eIgnoreCount);
300   }
301
302   key = GetKey(OptionNames::ConditionText);
303   if (key) {
304     success = options_dict.GetValueForKeyAsString(key, condition_ref);
305     if (!success) {
306       error.SetErrorStringWithFormat("%s key is not an string.",
307                                      GetKey(OptionNames::ConditionText));
308       return nullptr;
309     }
310     set_options.Set(eCondition);
311   }
312
313   std::unique_ptr<CommandData> cmd_data_up;
314   StructuredData::Dictionary *cmds_dict;
315   success = options_dict.GetValueForKeyAsDictionary(
316       CommandData::GetSerializationKey(), cmds_dict);
317   if (success && cmds_dict) {
318     Status cmds_error;
319     cmd_data_up = CommandData::CreateFromStructuredData(*cmds_dict, cmds_error);
320     if (cmds_error.Fail()) {
321       error.SetErrorStringWithFormat(
322           "Failed to deserialize breakpoint command options: %s.",
323           cmds_error.AsCString());
324       return nullptr;
325     }
326   }
327
328   auto bp_options = llvm::make_unique<BreakpointOptions>(
329       condition_ref.str().c_str(), enabled, 
330       ignore_count, one_shot, auto_continue);
331   if (cmd_data_up.get()) {
332     if (cmd_data_up->interpreter == eScriptLanguageNone)
333       bp_options->SetCommandDataCallback(cmd_data_up);
334     else {
335       ScriptInterpreter *interp =
336           target.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
337       if (!interp) {
338         error.SetErrorStringWithFormat(
339             "Can't set script commands - no script interpreter");
340         return nullptr;
341       }
342       if (interp->GetLanguage() != cmd_data_up->interpreter) {
343         error.SetErrorStringWithFormat(
344             "Current script language doesn't match breakpoint's language: %s",
345             ScriptInterpreter::LanguageToString(cmd_data_up->interpreter)
346                 .c_str());
347         return nullptr;
348       }
349       Status script_error;
350       script_error =
351           interp->SetBreakpointCommandCallback(bp_options.get(), cmd_data_up);
352       if (script_error.Fail()) {
353         error.SetErrorStringWithFormat("Error generating script callback: %s.",
354                                        error.AsCString());
355         return nullptr;
356       }
357     }
358   }
359
360   StructuredData::Dictionary *thread_spec_dict;
361   success = options_dict.GetValueForKeyAsDictionary(
362       ThreadSpec::GetSerializationKey(), thread_spec_dict);
363   if (success) {
364     Status thread_spec_error;
365     std::unique_ptr<ThreadSpec> thread_spec_up =
366         ThreadSpec::CreateFromStructuredData(*thread_spec_dict,
367                                              thread_spec_error);
368     if (thread_spec_error.Fail()) {
369       error.SetErrorStringWithFormat(
370           "Failed to deserialize breakpoint thread spec options: %s.",
371           thread_spec_error.AsCString());
372       return nullptr;
373     }
374     bp_options->SetThreadSpec(thread_spec_up);
375   }
376   return bp_options;
377 }
378
379 StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
380   StructuredData::DictionarySP options_dict_sp(
381       new StructuredData::Dictionary());
382   if (m_set_flags.Test(eEnabled))
383     options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState),
384                                     m_enabled);
385   if (m_set_flags.Test(eOneShot))
386     options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
387                                m_one_shot);
388   if (m_set_flags.Test(eAutoContinue))
389     options_dict_sp->AddBooleanItem(GetKey(OptionNames::AutoContinue),
390                                m_auto_continue);
391   if (m_set_flags.Test(eIgnoreCount))
392     options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
393                                     m_ignore_count);
394   if (m_set_flags.Test(eCondition))
395     options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
396                                    m_condition_text);
397          
398   if (m_set_flags.Test(eCallback) && m_baton_is_command_baton) {
399     auto cmd_baton =
400         std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
401     StructuredData::ObjectSP commands_sp =
402         cmd_baton->getItem()->SerializeToStructuredData();
403     if (commands_sp) {
404       options_dict_sp->AddItem(
405           BreakpointOptions::CommandData::GetSerializationKey(), commands_sp);
406     }
407   }
408   if (m_set_flags.Test(eThreadSpec) && m_thread_spec_ap) {
409     StructuredData::ObjectSP thread_spec_sp =
410         m_thread_spec_ap->SerializeToStructuredData();
411     options_dict_sp->AddItem(ThreadSpec::GetSerializationKey(), thread_spec_sp);
412   }
413
414   return options_dict_sp;
415 }
416
417 //------------------------------------------------------------------
418 // Callbacks
419 //------------------------------------------------------------------
420 void BreakpointOptions::SetCallback(BreakpointHitCallback callback,
421                                     const lldb::BatonSP &callback_baton_sp,
422                                     bool callback_is_synchronous) {
423   // FIXME: This seems unsafe.  If BatonSP actually *is* a CommandBaton, but
424   // in a shared_ptr<Baton> instead of a shared_ptr<CommandBaton>, then we will
425   // set m_baton_is_command_baton to false, which is incorrect. One possible
426   // solution is to make the base Baton class provide a method such as:
427   //     virtual StringRef getBatonId() const { return ""; }
428   // and have CommandBaton override this to return something unique, and then
429   // check for it here.  Another option might be to make Baton using the llvm
430   // casting infrastructure, so that we could write something like:
431   //     if (llvm::isa<CommandBaton>(callback_baton_sp))
432   // at relevant callsites instead of storing a boolean.
433   m_callback_is_synchronous = callback_is_synchronous;
434   m_callback = callback;
435   m_callback_baton_sp = callback_baton_sp;
436   m_baton_is_command_baton = false;
437   m_set_flags.Set(eCallback);
438 }
439
440 void BreakpointOptions::SetCallback(
441     BreakpointHitCallback callback,
442     const BreakpointOptions::CommandBatonSP &callback_baton_sp,
443     bool callback_is_synchronous) {
444   m_callback_is_synchronous = callback_is_synchronous;
445   m_callback = callback;
446   m_callback_baton_sp = callback_baton_sp;
447   m_baton_is_command_baton = true;
448   m_set_flags.Set(eCallback);
449 }
450
451 void BreakpointOptions::ClearCallback() {
452   m_callback = BreakpointOptions::NullCallback;
453   m_callback_is_synchronous = false;
454   m_callback_baton_sp.reset();
455   m_baton_is_command_baton = false;
456   m_set_flags.Clear(eCallback);
457 }
458
459 Baton *BreakpointOptions::GetBaton() { return m_callback_baton_sp.get(); }
460
461 const Baton *BreakpointOptions::GetBaton() const {
462   return m_callback_baton_sp.get();
463 }
464
465 bool BreakpointOptions::InvokeCallback(StoppointCallbackContext *context,
466                                        lldb::user_id_t break_id,
467                                        lldb::user_id_t break_loc_id) {
468   if (m_callback) {
469     if (context->is_synchronous == IsCallbackSynchronous()) {
470         return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data()
471                                           : nullptr,
472                       context, break_id, break_loc_id);
473     } else if (IsCallbackSynchronous()) {
474       // If a synchronous callback is called at async time, it should not say
475       // to stop.
476       return false;
477     }
478   }
479   return true;
480 }
481
482 bool BreakpointOptions::HasCallback() const {
483   return m_callback != BreakpointOptions::NullCallback;
484 }
485
486 bool BreakpointOptions::GetCommandLineCallbacks(StringList &command_list) {
487   if (!HasCallback())
488     return false;
489   if (!m_baton_is_command_baton)
490     return false;
491
492   auto cmd_baton = std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
493   CommandData *data = cmd_baton->getItem();
494   if (!data)
495     return false;
496   command_list = data->user_source;
497   return true;
498 }
499
500 void BreakpointOptions::SetCondition(const char *condition) {
501   if (!condition || condition[0] == '\0') {
502     condition = "";
503     m_set_flags.Clear(eCondition);
504   }
505   else
506     m_set_flags.Set(eCondition);
507
508   m_condition_text.assign(condition);
509   std::hash<std::string> hasher;
510   m_condition_text_hash = hasher(m_condition_text);
511 }
512
513 const char *BreakpointOptions::GetConditionText(size_t *hash) const {
514   if (!m_condition_text.empty()) {
515     if (hash)
516       *hash = m_condition_text_hash;
517
518     return m_condition_text.c_str();
519   } else {
520     return nullptr;
521   }
522 }
523
524 const ThreadSpec *BreakpointOptions::GetThreadSpecNoCreate() const {
525   return m_thread_spec_ap.get();
526 }
527
528 ThreadSpec *BreakpointOptions::GetThreadSpec() {
529   if (m_thread_spec_ap.get() == nullptr)
530   {
531     m_set_flags.Set(eThreadSpec);
532     m_thread_spec_ap.reset(new ThreadSpec());
533   }
534
535   return m_thread_spec_ap.get();
536 }
537
538 void BreakpointOptions::SetThreadID(lldb::tid_t thread_id) {
539   GetThreadSpec()->SetTID(thread_id);
540   m_set_flags.Set(eThreadSpec);
541 }
542
543 void BreakpointOptions::SetThreadSpec(
544     std::unique_ptr<ThreadSpec> &thread_spec_up) {
545   m_thread_spec_ap = std::move(thread_spec_up);
546   m_set_flags.Set(eThreadSpec);
547 }
548
549 void BreakpointOptions::GetDescription(Stream *s,
550                                        lldb::DescriptionLevel level) const {
551   // Figure out if there are any options not at their default value, and only
552   // print anything if there are:
553
554   if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue ||
555       (GetThreadSpecNoCreate() != nullptr &&
556        GetThreadSpecNoCreate()->HasSpecification())) {
557     if (level == lldb::eDescriptionLevelVerbose) {
558       s->EOL();
559       s->IndentMore();
560       s->Indent();
561       s->PutCString("Breakpoint Options:\n");
562       s->IndentMore();
563       s->Indent();
564     } else
565       s->PutCString(" Options: ");
566
567     if (m_ignore_count > 0)
568       s->Printf("ignore: %d ", m_ignore_count);
569     s->Printf("%sabled ", m_enabled ? "en" : "dis");
570
571     if (m_one_shot)
572       s->Printf("one-shot ");
573
574     if (m_auto_continue)
575       s->Printf("auto-continue ");
576
577     if (m_thread_spec_ap.get())
578       m_thread_spec_ap->GetDescription(s, level);
579
580     if (level == lldb::eDescriptionLevelFull) {
581       s->IndentLess();
582       s->IndentMore();
583     }
584   }
585
586   if (m_callback_baton_sp.get()) {
587     if (level != eDescriptionLevelBrief) {
588       s->EOL();
589       m_callback_baton_sp->GetDescription(s, level);
590     }
591   }
592   if (!m_condition_text.empty()) {
593     if (level != eDescriptionLevelBrief) {
594       s->EOL();
595       s->Printf("Condition: %s\n", m_condition_text.c_str());
596     }
597   }
598 }
599
600 void BreakpointOptions::CommandBaton::GetDescription(
601     Stream *s, lldb::DescriptionLevel level) const {
602   const CommandData *data = getItem();
603
604   if (level == eDescriptionLevelBrief) {
605     s->Printf(", commands = %s",
606               (data && data->user_source.GetSize() > 0) ? "yes" : "no");
607     return;
608   }
609
610   s->IndentMore();
611   s->Indent("Breakpoint commands");
612   if (data->interpreter != eScriptLanguageNone)
613     s->Printf(" (%s):\n",
614               ScriptInterpreter::LanguageToString(data->interpreter).c_str());
615   else
616     s->PutCString(":\n");
617
618   s->IndentMore();
619   if (data && data->user_source.GetSize() > 0) {
620     const size_t num_strings = data->user_source.GetSize();
621     for (size_t i = 0; i < num_strings; ++i) {
622       s->Indent(data->user_source.GetStringAtIndex(i));
623       s->EOL();
624     }
625   } else {
626     s->PutCString("No commands.\n");
627   }
628   s->IndentLess();
629   s->IndentLess();
630 }
631
632 void BreakpointOptions::SetCommandDataCallback(
633     std::unique_ptr<CommandData> &cmd_data) {
634   cmd_data->interpreter = eScriptLanguageNone;
635   auto baton_sp = std::make_shared<CommandBaton>(std::move(cmd_data));
636   SetCallback(BreakpointOptions::BreakpointOptionsCallbackFunction, baton_sp);
637   m_set_flags.Set(eCallback);
638 }
639
640 bool BreakpointOptions::BreakpointOptionsCallbackFunction(
641     void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
642     lldb::user_id_t break_loc_id) {
643   bool ret_value = true;
644   if (baton == nullptr)
645     return true;
646
647   CommandData *data = (CommandData *)baton;
648   StringList &commands = data->user_source;
649
650   if (commands.GetSize() > 0) {
651     ExecutionContext exe_ctx(context->exe_ctx_ref);
652     Target *target = exe_ctx.GetTargetPtr();
653     if (target) {
654       CommandReturnObject result;
655       Debugger &debugger = target->GetDebugger();
656       // Rig up the results secondary output stream to the debugger's, so the
657       // output will come out synchronously if the debugger is set up that way.
658
659       StreamSP output_stream(debugger.GetAsyncOutputStream());
660       StreamSP error_stream(debugger.GetAsyncErrorStream());
661       result.SetImmediateOutputStream(output_stream);
662       result.SetImmediateErrorStream(error_stream);
663
664       CommandInterpreterRunOptions options;
665       options.SetStopOnContinue(true);
666       options.SetStopOnError(data->stop_on_error);
667       options.SetEchoCommands(true);
668       options.SetPrintResults(true);
669       options.SetAddToHistory(false);
670
671       debugger.GetCommandInterpreter().HandleCommands(commands, &exe_ctx,
672                                                       options, result);
673       result.GetImmediateOutputStream()->Flush();
674       result.GetImmediateErrorStream()->Flush();
675     }
676   }
677   return ret_value;
678 }
679
680 void BreakpointOptions::Clear()
681 {
682   m_set_flags.Clear();
683   m_thread_spec_ap.release();
684   m_one_shot = false;
685   m_ignore_count = 0;
686   m_auto_continue = false;
687   m_callback = nullptr;
688   m_callback_baton_sp.reset();
689   m_baton_is_command_baton = false;
690   m_callback_is_synchronous = false;
691   m_enabled = false;
692   m_condition_text.clear();
693 }