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