1254721Semaste//===-- BreakpointOptions.cpp -----------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Breakpoint/BreakpointOptions.h"
11254721Semaste
12254721Semaste// C Includes
13254721Semaste// C++ Includes
14254721Semaste// Other libraries and framework includes
15254721Semaste// Project includes
16254721Semaste#include "lldb/Core/Stream.h"
17254721Semaste#include "lldb/Core/StringList.h"
18254721Semaste#include "lldb/Core/Value.h"
19254721Semaste#include "lldb/Breakpoint/StoppointCallbackContext.h"
20254721Semaste#include "lldb/Target/Process.h"
21254721Semaste#include "lldb/Target/Target.h"
22254721Semaste#include "lldb/Target/ThreadSpec.h"
23254721Semaste#include "lldb/Expression/ClangUserExpression.h"
24254721Semaste
25254721Semasteusing namespace lldb;
26254721Semasteusing namespace lldb_private;
27254721Semaste
28254721Semastebool
29254721SemasteBreakpointOptions::NullCallback (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
30254721Semaste{
31254721Semaste    return true;
32254721Semaste}
33254721Semaste
34254721Semaste//----------------------------------------------------------------------
35254721Semaste// BreakpointOptions constructor
36254721Semaste//----------------------------------------------------------------------
37254721SemasteBreakpointOptions::BreakpointOptions() :
38254721Semaste    m_callback (BreakpointOptions::NullCallback),
39254721Semaste    m_callback_baton_sp (),
40254721Semaste    m_callback_is_synchronous (false),
41254721Semaste    m_enabled (true),
42254721Semaste    m_one_shot (false),
43254721Semaste    m_ignore_count (0),
44254721Semaste    m_thread_spec_ap (),
45254721Semaste    m_condition_text (),
46254721Semaste    m_condition_text_hash (0)
47254721Semaste{
48254721Semaste}
49254721Semaste
50254721Semaste//----------------------------------------------------------------------
51254721Semaste// BreakpointOptions copy constructor
52254721Semaste//----------------------------------------------------------------------
53254721SemasteBreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) :
54254721Semaste    m_callback (rhs.m_callback),
55254721Semaste    m_callback_baton_sp (rhs.m_callback_baton_sp),
56254721Semaste    m_callback_is_synchronous (rhs.m_callback_is_synchronous),
57254721Semaste    m_enabled (rhs.m_enabled),
58254721Semaste    m_one_shot (rhs.m_one_shot),
59254721Semaste    m_ignore_count (rhs.m_ignore_count),
60254721Semaste    m_thread_spec_ap ()
61254721Semaste{
62254721Semaste    if (rhs.m_thread_spec_ap.get() != NULL)
63254721Semaste        m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get()));
64254721Semaste    m_condition_text = rhs.m_condition_text;
65254721Semaste    m_condition_text_hash = rhs.m_condition_text_hash;
66254721Semaste}
67254721Semaste
68254721Semaste//----------------------------------------------------------------------
69254721Semaste// BreakpointOptions assignment operator
70254721Semaste//----------------------------------------------------------------------
71254721Semasteconst BreakpointOptions&
72254721SemasteBreakpointOptions::operator=(const BreakpointOptions& rhs)
73254721Semaste{
74254721Semaste    m_callback = rhs.m_callback;
75254721Semaste    m_callback_baton_sp = rhs.m_callback_baton_sp;
76254721Semaste    m_callback_is_synchronous = rhs.m_callback_is_synchronous;
77254721Semaste    m_enabled = rhs.m_enabled;
78254721Semaste    m_one_shot = rhs.m_one_shot;
79254721Semaste    m_ignore_count = rhs.m_ignore_count;
80254721Semaste    if (rhs.m_thread_spec_ap.get() != NULL)
81254721Semaste        m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
82254721Semaste    m_condition_text = rhs.m_condition_text;
83254721Semaste    m_condition_text_hash = rhs.m_condition_text_hash;
84254721Semaste    return *this;
85254721Semaste}
86254721Semaste
87254721SemasteBreakpointOptions *
88254721SemasteBreakpointOptions::CopyOptionsNoCallback (BreakpointOptions &orig)
89254721Semaste{
90254721Semaste    BreakpointHitCallback orig_callback = orig.m_callback;
91254721Semaste    lldb::BatonSP orig_callback_baton_sp = orig.m_callback_baton_sp;
92254721Semaste    bool orig_is_sync = orig.m_callback_is_synchronous;
93254721Semaste
94254721Semaste    orig.ClearCallback();
95254721Semaste    BreakpointOptions *ret_val = new BreakpointOptions(orig);
96254721Semaste
97254721Semaste    orig.SetCallback (orig_callback, orig_callback_baton_sp, orig_is_sync);
98254721Semaste
99254721Semaste    return ret_val;
100254721Semaste}
101254721Semaste
102254721Semaste//----------------------------------------------------------------------
103254721Semaste// Destructor
104254721Semaste//----------------------------------------------------------------------
105254721SemasteBreakpointOptions::~BreakpointOptions()
106254721Semaste{
107254721Semaste}
108254721Semaste
109254721Semaste//------------------------------------------------------------------
110254721Semaste// Callbacks
111254721Semaste//------------------------------------------------------------------
112254721Semastevoid
113254721SemasteBreakpointOptions::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool callback_is_synchronous)
114254721Semaste{
115254721Semaste    m_callback_is_synchronous = callback_is_synchronous;
116254721Semaste    m_callback = callback;
117254721Semaste    m_callback_baton_sp = callback_baton_sp;
118254721Semaste}
119254721Semaste
120254721Semastevoid
121254721SemasteBreakpointOptions::ClearCallback ()
122254721Semaste{
123254721Semaste    m_callback = BreakpointOptions::NullCallback;
124254721Semaste    m_callback_is_synchronous = false;
125254721Semaste    m_callback_baton_sp.reset();
126254721Semaste}
127254721Semaste
128254721SemasteBaton *
129254721SemasteBreakpointOptions::GetBaton ()
130254721Semaste{
131254721Semaste    return m_callback_baton_sp.get();
132254721Semaste}
133254721Semaste
134254721Semasteconst Baton *
135254721SemasteBreakpointOptions::GetBaton () const
136254721Semaste{
137254721Semaste    return m_callback_baton_sp.get();
138254721Semaste}
139254721Semaste
140254721Semastebool
141254721SemasteBreakpointOptions::InvokeCallback (StoppointCallbackContext *context,
142254721Semaste                                   lldb::user_id_t break_id,
143254721Semaste                                   lldb::user_id_t break_loc_id)
144254721Semaste{
145254721Semaste    if (m_callback && context->is_synchronous == IsCallbackSynchronous())
146254721Semaste    {
147254721Semaste        return m_callback (m_callback_baton_sp ? m_callback_baton_sp->m_data : NULL,
148254721Semaste                           context,
149254721Semaste                           break_id,
150254721Semaste                           break_loc_id);
151254721Semaste    }
152254721Semaste    else
153254721Semaste        return true;
154254721Semaste}
155254721Semaste
156254721Semastebool
157254721SemasteBreakpointOptions::HasCallback ()
158254721Semaste{
159254721Semaste    return m_callback != BreakpointOptions::NullCallback;
160254721Semaste}
161254721Semaste
162254721Semastevoid
163254721SemasteBreakpointOptions::SetCondition (const char *condition)
164254721Semaste{
165254721Semaste    if (!condition)
166254721Semaste        condition = "";
167254721Semaste
168254721Semaste    m_condition_text.assign(condition);
169254721Semaste    std::hash<std::string> hasher;
170254721Semaste    m_condition_text_hash = hasher(m_condition_text);
171254721Semaste}
172254721Semaste
173254721Semasteconst char *
174254721SemasteBreakpointOptions::GetConditionText (size_t *hash) const
175254721Semaste{
176254721Semaste    if (!m_condition_text.empty())
177254721Semaste    {
178254721Semaste        if (hash)
179254721Semaste            *hash = m_condition_text_hash;
180254721Semaste
181254721Semaste        return m_condition_text.c_str();
182254721Semaste    }
183254721Semaste    else
184254721Semaste    {
185254721Semaste        return NULL;
186254721Semaste    }
187254721Semaste}
188254721Semaste
189254721Semasteconst ThreadSpec *
190254721SemasteBreakpointOptions::GetThreadSpecNoCreate () const
191254721Semaste{
192254721Semaste    return m_thread_spec_ap.get();
193254721Semaste}
194254721Semaste
195254721SemasteThreadSpec *
196254721SemasteBreakpointOptions::GetThreadSpec ()
197254721Semaste{
198254721Semaste    if (m_thread_spec_ap.get() == NULL)
199254721Semaste        m_thread_spec_ap.reset (new ThreadSpec());
200254721Semaste
201254721Semaste    return m_thread_spec_ap.get();
202254721Semaste}
203254721Semaste
204254721Semastevoid
205254721SemasteBreakpointOptions::SetThreadID (lldb::tid_t thread_id)
206254721Semaste{
207254721Semaste    GetThreadSpec()->SetTID(thread_id);
208254721Semaste}
209254721Semaste
210254721Semastevoid
211254721SemasteBreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const
212254721Semaste{
213254721Semaste
214254721Semaste    // Figure out if there are any options not at their default value, and only print
215254721Semaste    // anything if there are:
216254721Semaste
217254721Semaste    if (m_ignore_count != 0 || !m_enabled || m_one_shot || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ()))
218254721Semaste    {
219254721Semaste        if (level == lldb::eDescriptionLevelVerbose)
220254721Semaste        {
221254721Semaste            s->EOL ();
222254721Semaste            s->IndentMore();
223254721Semaste            s->Indent();
224254721Semaste            s->PutCString("Breakpoint Options:\n");
225254721Semaste            s->IndentMore();
226254721Semaste            s->Indent();
227254721Semaste        }
228254721Semaste        else
229254721Semaste            s->PutCString(" Options: ");
230254721Semaste
231254721Semaste        if (m_ignore_count > 0)
232254721Semaste            s->Printf("ignore: %d ", m_ignore_count);
233254721Semaste        s->Printf("%sabled ", m_enabled ? "en" : "dis");
234254721Semaste
235254721Semaste        if (m_one_shot)
236254721Semaste            s->Printf ("one-shot ");
237254721Semaste
238254721Semaste        if (m_thread_spec_ap.get())
239254721Semaste            m_thread_spec_ap->GetDescription (s, level);
240254721Semaste        else if (level == eDescriptionLevelBrief)
241254721Semaste            s->PutCString ("thread spec: no ");
242254721Semaste        if (level == lldb::eDescriptionLevelFull)
243254721Semaste        {
244254721Semaste            s->IndentLess();
245254721Semaste            s->IndentMore();
246254721Semaste        }
247254721Semaste    }
248254721Semaste
249254721Semaste    if (m_callback_baton_sp.get())
250254721Semaste    {
251254721Semaste        if (level != eDescriptionLevelBrief)
252254721Semaste        {
253254721Semaste            s->EOL();
254254721Semaste            m_callback_baton_sp->GetDescription (s, level);
255254721Semaste        }
256254721Semaste    }
257254721Semaste    if (!m_condition_text.empty())
258254721Semaste    {
259254721Semaste       if (level != eDescriptionLevelBrief)
260254721Semaste       {
261254721Semaste            s->EOL();
262254721Semaste            s->Printf("Condition: %s\n", m_condition_text.c_str());
263254721Semaste        }
264254721Semaste    }
265254721Semaste}
266254721Semaste
267254721Semastevoid
268254721SemasteBreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLevel level) const
269254721Semaste{
270254721Semaste    CommandData *data = (CommandData *)m_data;
271254721Semaste
272254721Semaste    if (level == eDescriptionLevelBrief)
273254721Semaste    {
274254721Semaste        s->Printf (", commands = %s", (data && data->user_source.GetSize() > 0) ? "yes" : "no");
275254721Semaste        return;
276254721Semaste    }
277254721Semaste
278254721Semaste    s->IndentMore ();
279254721Semaste    s->Indent("Breakpoint commands:\n");
280254721Semaste
281254721Semaste    s->IndentMore ();
282254721Semaste    if (data && data->user_source.GetSize() > 0)
283254721Semaste    {
284254721Semaste        const size_t num_strings = data->user_source.GetSize();
285254721Semaste        for (size_t i = 0; i < num_strings; ++i)
286254721Semaste        {
287254721Semaste            s->Indent(data->user_source.GetStringAtIndex(i));
288254721Semaste            s->EOL();
289254721Semaste        }
290254721Semaste    }
291254721Semaste    else
292254721Semaste    {
293254721Semaste        s->PutCString ("No commands.\n");
294254721Semaste    }
295254721Semaste    s->IndentLess ();
296254721Semaste    s->IndentLess ();
297254721Semaste}
298254721Semaste
299