blob: 949bbbed74ed37f7ed7a4ce04c7aaf556ce40f0b [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- BreakpointIDList.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/BreakpointIDList.h"
11
12#include "lldb/Breakpoint/Breakpoint.h"
13#include "lldb/Breakpoint/BreakpointLocation.h"
14#include "lldb/Interpreter/CommandReturnObject.h"
Jim Ingham84cdc152010-06-15 19:49:27 +000015#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Target/Target.h"
17
18using namespace lldb;
19using namespace lldb_private;
20
21//----------------------------------------------------------------------
22// class BreakpointIDList
23//----------------------------------------------------------------------
24
25BreakpointIDList::BreakpointIDList () :
26m_invalid_id (LLDB_INVALID_BREAK_ID, LLDB_INVALID_BREAK_ID)
27{
28}
29
30BreakpointIDList::~BreakpointIDList ()
31{
32}
33
Greg Clayton54e7afa2010-07-09 20:39:50 +000034size_t
35BreakpointIDList::GetSize()
Chris Lattner24943d22010-06-08 16:52:24 +000036{
37 return m_breakpoint_ids.size();
38}
39
40BreakpointID &
Greg Clayton54e7afa2010-07-09 20:39:50 +000041BreakpointIDList::GetBreakpointIDAtIndex (uint32_t index)
Chris Lattner24943d22010-06-08 16:52:24 +000042{
43 if (index < m_breakpoint_ids.size())
44 return m_breakpoint_ids[index];
45 else
46 return m_invalid_id;
47}
48
49bool
Greg Clayton54e7afa2010-07-09 20:39:50 +000050BreakpointIDList::RemoveBreakpointIDAtIndex (uint32_t index)
Chris Lattner24943d22010-06-08 16:52:24 +000051{
Greg Clayton54e7afa2010-07-09 20:39:50 +000052 if (index >= m_breakpoint_ids.size())
53 return false;
Chris Lattner24943d22010-06-08 16:52:24 +000054
Greg Clayton54e7afa2010-07-09 20:39:50 +000055 m_breakpoint_ids.erase (m_breakpoint_ids.begin() + index);
56 return true;
Chris Lattner24943d22010-06-08 16:52:24 +000057}
58
59void
60BreakpointIDList::Clear()
61{
62 m_breakpoint_ids.clear ();
63}
64
65bool
66BreakpointIDList::AddBreakpointID (BreakpointID bp_id)
67{
68 m_breakpoint_ids.push_back (bp_id);
69
70 return true; // We don't do any verification in this function, so always return true.
71}
72
73bool
74BreakpointIDList::AddBreakpointID (const char *bp_id_str)
75{
76 BreakpointID temp_bp_id;
77 break_id_t bp_id;
78 break_id_t loc_id;
79
80 bool success = BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id);
81
82 if (success)
83 {
84 temp_bp_id.SetID (bp_id, loc_id);
85 m_breakpoint_ids.push_back (temp_bp_id);
86 }
87
88 return success;
89}
90
91bool
Greg Clayton54e7afa2010-07-09 20:39:50 +000092BreakpointIDList::FindBreakpointID (BreakpointID &bp_id, uint32_t *position)
Chris Lattner24943d22010-06-08 16:52:24 +000093{
94 bool success = false;
95 BreakpointIDArray::iterator tmp_pos;
96
Greg Clayton54e7afa2010-07-09 20:39:50 +000097 for (size_t i = 0; i < m_breakpoint_ids.size(); ++i)
Chris Lattner24943d22010-06-08 16:52:24 +000098 {
99 BreakpointID tmp_id = m_breakpoint_ids[i];
100 if (tmp_id.GetBreakpointID() == bp_id.GetBreakpointID()
101 && tmp_id.GetLocationID() == bp_id.GetLocationID())
102 {
103 success = true;
104 *position = i;
105 return true;
106 }
107 }
108
109 return false;
110}
111
112bool
Greg Clayton54e7afa2010-07-09 20:39:50 +0000113BreakpointIDList::FindBreakpointID (const char *bp_id_str, uint32_t *position)
Chris Lattner24943d22010-06-08 16:52:24 +0000114{
115 BreakpointID temp_bp_id;
116 break_id_t bp_id;
117 break_id_t loc_id;
118
119 if (BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id))
120 {
121 temp_bp_id.SetID (bp_id, loc_id);
122 return FindBreakpointID (temp_bp_id, position);
123 }
124 else
125 return false;
126}
127
128void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000129BreakpointIDList::InsertStringArray (const char **string_array, uint32_t array_size, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000130{
131 if (string_array == NULL)
132 return;
133
Greg Clayton54e7afa2010-07-09 20:39:50 +0000134 for (uint32_t i = 0; i < array_size; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000135 {
136 break_id_t bp_id;
137 break_id_t loc_id;
138
139 if (BreakpointID::ParseCanonicalReference (string_array[i], &bp_id, &loc_id))
140 {
141 if (bp_id != LLDB_INVALID_BREAK_ID)
142 {
143 BreakpointID temp_bp_id(bp_id, loc_id);
144 m_breakpoint_ids.push_back (temp_bp_id);
145 }
146 else
147 {
148 result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", string_array[i]);
149 result.SetStatus (eReturnStatusFailed);
150 return;
151 }
152 }
153 }
154 result.SetStatus (eReturnStatusSuccessFinishNoResult);
155}
156
157
158// This function takes OLD_ARGS, which is usually the result of breaking the command string arguments into
159// an array of space-separated strings, and searches through the arguments for any breakpoint ID range specifiers.
160// Any string in the array that is not part of an ID range specifier is copied directly into NEW_ARGS. If any
161// ID range specifiers are found, the range is interpreted and a list of canonical breakpoint IDs corresponding to
162// all the current breakpoints and locations in the range are added to NEW_ARGS. When this function is done,
163// NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced by the members of the range.
164
165void
166BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result,
167 Args &new_args)
168{
Greg Clayton54e7afa2010-07-09 20:39:50 +0000169 std::string range_start;
Chris Lattner24943d22010-06-08 16:52:24 +0000170 const char *range_end;
171 const char *current_arg;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000172 const size_t num_old_args = old_args.GetArgumentCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000173
Greg Clayton54e7afa2010-07-09 20:39:50 +0000174 for (size_t i = 0; i < num_old_args; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000175 {
176 bool is_range = false;
177 current_arg = old_args.GetArgumentAtIndex (i);
178
Greg Clayton54e7afa2010-07-09 20:39:50 +0000179 uint32_t range_start_len = 0;
180 uint32_t range_end_pos = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000181 if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos))
182 {
183 is_range = true;
184 range_start = (char *) malloc (range_start_len + 1);
Greg Clayton54e7afa2010-07-09 20:39:50 +0000185 range_start.assign (current_arg, range_start_len);
Chris Lattner24943d22010-06-08 16:52:24 +0000186 range_end = current_arg + range_end_pos;
187 }
188 else if ((i + 2 < num_old_args)
189 && BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1))
190 && BreakpointID::IsValidIDExpression (current_arg)
191 && BreakpointID::IsValidIDExpression (old_args.GetArgumentAtIndex (i+2)))
192 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000193 range_start.assign (current_arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000194 range_end = old_args.GetArgumentAtIndex (i+2);
195 is_range = true;
196 i = i+2;
197 }
198
199 if (is_range)
200 {
201 break_id_t start_bp_id;
202 break_id_t end_bp_id;
203 break_id_t start_loc_id;
204 break_id_t end_loc_id;
205
Greg Clayton54e7afa2010-07-09 20:39:50 +0000206 BreakpointID::ParseCanonicalReference (range_start.c_str(), &start_bp_id, &start_loc_id);
Chris Lattner24943d22010-06-08 16:52:24 +0000207 BreakpointID::ParseCanonicalReference (range_end, &end_bp_id, &end_loc_id);
208
209 if ((start_bp_id == LLDB_INVALID_BREAK_ID)
210 || (! target->GetBreakpointByID (start_bp_id)))
211 {
212 new_args.Clear();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000213 result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_start.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000214 result.SetStatus (eReturnStatusFailed);
215 return;
216 }
217
218 if ((end_bp_id == LLDB_INVALID_BREAK_ID)
219 || (! target->GetBreakpointByID (end_bp_id)))
220 {
221 new_args.Clear();
222 result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_end);
223 result.SetStatus (eReturnStatusFailed);
224 return;
225 }
226
227 // We have valid range starting & ending breakpoint IDs. Go through all the breakpoints in the
228 // target and find all the breakpoints that fit into this range, and add them to new_args.
229
230 const BreakpointList& breakpoints = target->GetBreakpointList();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000231 const size_t num_breakpoints = breakpoints.GetSize();
232 for (size_t j = 0; j < num_breakpoints; ++j)
Chris Lattner24943d22010-06-08 16:52:24 +0000233 {
234 Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (j).get();
235 break_id_t cur_bp_id = breakpoint->GetID();
236
237 if ((cur_bp_id < start_bp_id) || (cur_bp_id > end_bp_id))
238 continue;
239
Greg Clayton54e7afa2010-07-09 20:39:50 +0000240 const size_t num_locations = breakpoint->GetNumLocations();
Chris Lattner24943d22010-06-08 16:52:24 +0000241
242 if ((cur_bp_id == start_bp_id) && (start_loc_id != LLDB_INVALID_BREAK_ID))
243 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000244 for (size_t k = 0; k < num_locations; ++k)
Chris Lattner24943d22010-06-08 16:52:24 +0000245 {
246 BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get();
247 if (bp_loc->GetID() >= start_loc_id)
248 {
249 StreamString canonical_id_str;
250 BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID());
251 new_args.AppendArgument (canonical_id_str.GetData());
252 }
253 }
254 }
255 else if ((cur_bp_id == end_bp_id) && (end_loc_id != LLDB_INVALID_BREAK_ID))
256 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000257 for (size_t k = 0; k < num_locations; ++k)
Chris Lattner24943d22010-06-08 16:52:24 +0000258 {
259 BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get();
260 if (bp_loc->GetID() <= end_loc_id)
261 {
262 StreamString canonical_id_str;
263 BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID());
264 new_args.AppendArgument (canonical_id_str.GetData());
265 }
266 }
267 }
268 else
269 {
270 StreamString canonical_id_str;
271 BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, LLDB_INVALID_BREAK_ID);
272 new_args.AppendArgument (canonical_id_str.GetData());
273 }
274 }
275 }
276 else // else is_range was false
277 {
278 new_args.AppendArgument (current_arg);
279 }
280 }
281
282 result.SetStatus (eReturnStatusSuccessFinishNoResult);
283 return;
284}
285
Chris Lattner24943d22010-06-08 16:52:24 +0000286bool
Greg Clayton54e7afa2010-07-09 20:39:50 +0000287BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, uint32_t *range_start_len, uint32_t *range_end_pos)
Chris Lattner24943d22010-06-08 16:52:24 +0000288{
289 bool is_range_expression = false;
290 std::string arg_str = in_string;
291 std::string::size_type idx;
292 std::string::size_type start_pos = 0;
293
Chris Lattner24943d22010-06-08 16:52:24 +0000294 *range_start_len = 0;
295 *range_end_pos = 0;
296
297 int specifiers_size = 0;
298 for (int i = 0; BreakpointID::g_range_specifiers[i] != NULL; ++i)
299 ++specifiers_size;
300
301 for (int i = 0; i < specifiers_size && !is_range_expression; ++i)
302 {
303 const char *specifier_str = BreakpointID::g_range_specifiers[i];
304 int len = strlen (specifier_str);
305 idx = arg_str.find (BreakpointID::g_range_specifiers[i]);
306 if (idx != std::string::npos)
307 {
308 *range_start_len = idx - start_pos;
309 std::string start_str = arg_str.substr (start_pos, *range_start_len);
310 if (idx + len < arg_str.length())
311 {
312 *range_end_pos = idx + len;
313 std::string end_str = arg_str.substr (*range_end_pos);
314 if (BreakpointID::IsValidIDExpression (start_str.c_str())
315 && BreakpointID::IsValidIDExpression (end_str.c_str()))
316 {
317 is_range_expression = true;
318 //*range_start = start_str;
319 //*range_end = end_str;
320 }
321 }
322 }
323 }
324
325 if (!is_range_expression)
326 {
327 *range_start_len = 0;
328 *range_end_pos = 0;
329 }
330
331 return is_range_expression;
332}