]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/tid-parse.c
Update copyright year range in all GDB files
[thirdparty/binutils-gdb.git] / gdb / tid-parse.c
CommitLineData
5d5658a1
PA
1/* TID parsing for GDB, the GNU debugger.
2
e2882c85 3 Copyright (C) 2015-2018 Free Software Foundation, Inc.
5d5658a1
PA
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
21#include "tid-parse.h"
22#include "inferior.h"
23#include "gdbthread.h"
24#include <ctype.h>
25
26/* See tid-parse.h. */
27
28void ATTRIBUTE_NORETURN
29invalid_thread_id_error (const char *string)
30{
31 error (_("Invalid thread ID: %s"), string);
32}
33
3f5b7598
PA
34/* Wrapper for get_number_trailer that throws an error if we get back
35 a negative number. We'll see a negative value if the number is
36 stored in a negative convenience variable (e.g., $minus_one = -1).
37 STRING is the parser string to be used in the error message if we
38 do get back a negative number. */
39
40static int
41get_positive_number_trailer (const char **pp, int trailer, const char *string)
42{
43 int num;
44
45 num = get_number_trailer (pp, trailer);
46 if (num < 0)
47 error (_("negative value: %s"), string);
48 return num;
49}
50
5d5658a1
PA
51/* See tid-parse.h. */
52
53struct thread_info *
54parse_thread_id (const char *tidstr, const char **end)
55{
56 const char *number = tidstr;
57 const char *dot, *p1;
58 struct thread_info *tp;
59 struct inferior *inf;
60 int thr_num;
61 int explicit_inf_id = 0;
62
63 dot = strchr (number, '.');
64
65 if (dot != NULL)
66 {
67 /* Parse number to the left of the dot. */
68 int inf_num;
69
70 p1 = number;
3f5b7598 71 inf_num = get_positive_number_trailer (&p1, '.', number);
5d5658a1
PA
72 if (inf_num == 0)
73 invalid_thread_id_error (number);
74
75 inf = find_inferior_id (inf_num);
76 if (inf == NULL)
77 error (_("No inferior number '%d'"), inf_num);
78
79 explicit_inf_id = 1;
80 p1 = dot + 1;
81 }
82 else
83 {
84 inf = current_inferior ();
85
86 p1 = number;
87 }
88
3f5b7598 89 thr_num = get_positive_number_trailer (&p1, 0, number);
5d5658a1
PA
90 if (thr_num == 0)
91 invalid_thread_id_error (number);
92
93 ALL_THREADS (tp)
94 {
95 if (ptid_get_pid (tp->ptid) == inf->pid
96 && tp->per_inf_num == thr_num)
97 break;
98 }
99
100 if (tp == NULL)
101 {
102 if (show_inferior_qualified_tids () || explicit_inf_id)
103 error (_("Unknown thread %d.%d."), inf->num, thr_num);
104 else
105 error (_("Unknown thread %d."), thr_num);
106 }
107
108 if (end != NULL)
109 *end = p1;
110
111 return tp;
112}
113
114/* See tid-parse.h. */
115
bfd28288
PA
116tid_range_parser::tid_range_parser (const char *tidlist,
117 int default_inferior)
118{
119 init (tidlist, default_inferior);
120}
121
122/* See tid-parse.h. */
123
5d5658a1 124void
bfd28288 125tid_range_parser::init (const char *tidlist, int default_inferior)
5d5658a1 126{
bfd28288
PA
127 m_state = STATE_INFERIOR;
128 m_cur_tok = tidlist;
129 m_inf_num = 0;
130 m_qualified = false;
131 m_default_inferior = default_inferior;
5d5658a1
PA
132}
133
134/* See tid-parse.h. */
135
bfd28288
PA
136bool
137tid_range_parser::finished () const
5d5658a1 138{
bfd28288 139 switch (m_state)
5d5658a1 140 {
bfd28288
PA
141 case STATE_INFERIOR:
142 return *m_cur_tok == '\0';
143 case STATE_THREAD_RANGE:
144 case STATE_STAR_RANGE:
145 return m_range_parser.finished ();
5d5658a1
PA
146 }
147
148 gdb_assert_not_reached (_("unhandled state"));
149}
150
151/* See tid-parse.h. */
152
153const char *
bfd28288 154tid_range_parser::cur_tok () const
5d5658a1 155{
bfd28288 156 switch (m_state)
5d5658a1 157 {
bfd28288
PA
158 case STATE_INFERIOR:
159 return m_cur_tok;
160 case STATE_THREAD_RANGE:
161 case STATE_STAR_RANGE:
162 return m_range_parser.cur_tok ();
5d5658a1
PA
163 }
164
165 gdb_assert_not_reached (_("unhandled state"));
166}
167
5d5658a1 168void
bfd28288 169tid_range_parser::skip_range ()
5d5658a1 170{
bfd28288
PA
171 gdb_assert (m_state == STATE_THREAD_RANGE
172 || m_state == STATE_STAR_RANGE);
5d5658a1 173
bfd28288
PA
174 m_range_parser.skip_range ();
175 init (m_range_parser.cur_tok (), m_default_inferior);
5d5658a1
PA
176}
177
178/* See tid-parse.h. */
179
bfd28288
PA
180bool
181tid_range_parser::tid_is_qualified () const
5d5658a1 182{
bfd28288 183 return m_qualified;
5d5658a1
PA
184}
185
bfd28288
PA
186/* Helper for tid_range_parser::get_tid and
187 tid_range_parser::get_tid_range. Return the next range if THR_END
5d5658a1
PA
188 is non-NULL, return a single thread ID otherwise. */
189
bfd28288
PA
190bool
191tid_range_parser::get_tid_or_range (int *inf_num,
192 int *thr_start, int *thr_end)
5d5658a1 193{
bfd28288 194 if (m_state == STATE_INFERIOR)
5d5658a1
PA
195 {
196 const char *p;
197 const char *space;
198
bfd28288 199 space = skip_to_space (m_cur_tok);
5d5658a1 200
bfd28288 201 p = m_cur_tok;
5d5658a1
PA
202 while (p < space && *p != '.')
203 p++;
204 if (p < space)
205 {
206 const char *dot = p;
207
208 /* Parse number to the left of the dot. */
bfd28288
PA
209 p = m_cur_tok;
210 m_inf_num = get_positive_number_trailer (&p, '.', m_cur_tok);
211 if (m_inf_num == 0)
3f5b7598 212 return 0;
5d5658a1 213
bfd28288 214 m_qualified = true;
5d5658a1
PA
215 p = dot + 1;
216
217 if (isspace (*p))
bfd28288 218 return false;
5d5658a1
PA
219 }
220 else
221 {
bfd28288
PA
222 m_inf_num = m_default_inferior;
223 m_qualified = false;
224 p = m_cur_tok;
5d5658a1
PA
225 }
226
bfd28288 227 m_range_parser.init (p);
71ef29a8
PA
228 if (p[0] == '*' && (p[1] == '\0' || isspace (p[1])))
229 {
230 /* Setup the number range parser to return numbers in the
231 whole [1,INT_MAX] range. */
f1735a53 232 m_range_parser.setup_range (1, INT_MAX, skip_spaces (p + 1));
bfd28288 233 m_state = STATE_STAR_RANGE;
71ef29a8
PA
234 }
235 else
bfd28288 236 m_state = STATE_THREAD_RANGE;
5d5658a1
PA
237 }
238
bfd28288
PA
239 *inf_num = m_inf_num;
240 *thr_start = m_range_parser.get_number ();
3f5b7598 241 if (*thr_start < 0)
bfd28288 242 error (_("negative value: %s"), m_cur_tok);
5d5658a1 243 if (*thr_start == 0)
3f5b7598 244 {
bfd28288
PA
245 m_state = STATE_INFERIOR;
246 return false;
3f5b7598 247 }
5d5658a1
PA
248
249 /* If we successfully parsed a thread number or finished parsing a
250 thread range, switch back to assuming the next TID is
251 inferior-qualified. */
bfd28288 252 if (!m_range_parser.in_range ())
5d5658a1 253 {
bfd28288
PA
254 m_state = STATE_INFERIOR;
255 m_cur_tok = m_range_parser.cur_tok ();
5d5658a1
PA
256
257 if (thr_end != NULL)
258 *thr_end = *thr_start;
259 }
260
261 /* If we're midway through a range, and the caller wants the end
262 value, return it and skip to the end of the range. */
71ef29a8 263 if (thr_end != NULL
bfd28288
PA
264 && (m_state == STATE_THREAD_RANGE
265 || m_state == STATE_STAR_RANGE))
5d5658a1 266 {
bfd28288
PA
267 *thr_end = m_range_parser.end_value ();
268
269 skip_range ();
5d5658a1
PA
270 }
271
272 return (*inf_num != 0 && *thr_start != 0);
273}
274
275/* See tid-parse.h. */
276
bfd28288
PA
277bool
278tid_range_parser::get_tid_range (int *inf_num,
279 int *thr_start, int *thr_end)
5d5658a1
PA
280{
281 gdb_assert (inf_num != NULL && thr_start != NULL && thr_end != NULL);
282
bfd28288 283 return get_tid_or_range (inf_num, thr_start, thr_end);
5d5658a1
PA
284}
285
286/* See tid-parse.h. */
287
bfd28288
PA
288bool
289tid_range_parser::get_tid (int *inf_num, int *thr_num)
5d5658a1
PA
290{
291 gdb_assert (inf_num != NULL && thr_num != NULL);
292
bfd28288 293 return get_tid_or_range (inf_num, thr_num, NULL);
5d5658a1
PA
294}
295
296/* See tid-parse.h. */
297
bfd28288
PA
298bool
299tid_range_parser::in_star_range () const
71ef29a8 300{
bfd28288 301 return m_state == STATE_STAR_RANGE;
71ef29a8
PA
302}
303
304/* See gdbthread.h. */
305
5d5658a1
PA
306int
307tid_is_in_list (const char *list, int default_inferior,
308 int inf_num, int thr_num)
309{
5d5658a1
PA
310 if (list == NULL || *list == '\0')
311 return 1;
312
bfd28288
PA
313 tid_range_parser parser (list, default_inferior);
314 while (!parser.finished ())
5d5658a1
PA
315 {
316 int tmp_inf, tmp_thr_start, tmp_thr_end;
317
bfd28288
PA
318 if (!parser.get_tid_range (&tmp_inf, &tmp_thr_start, &tmp_thr_end))
319 invalid_thread_id_error (parser.cur_tok ());
5d5658a1
PA
320 if (tmp_inf == inf_num
321 && tmp_thr_start <= thr_num && thr_num <= tmp_thr_end)
322 return 1;
323 }
324 return 0;
325}