GDB (xrefs)
Loading...
Searching...
No Matches
tid-parse.c
Go to the documentation of this file.
1/* TID parsing for GDB, the GNU debugger.
2
3 Copyright (C) 2015-2023 Free Software Foundation, Inc.
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
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
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 inferior *inf;
59 int thr_num;
60 int explicit_inf_id = 0;
61
62 dot = strchr (number, '.');
63
64 if (dot != NULL)
65 {
66 /* Parse number to the left of the dot. */
67 int inf_num;
68
69 p1 = number;
70 inf_num = get_positive_number_trailer (&p1, '.', number);
71 if (inf_num == 0)
73
74 inf = find_inferior_id (inf_num);
75 if (inf == NULL)
76 error (_("No inferior number '%d'"), inf_num);
77
78 explicit_inf_id = 1;
79 p1 = dot + 1;
80 }
81 else
82 {
84
85 p1 = number;
86 }
87
88 thr_num = get_positive_number_trailer (&p1, 0, number);
89 if (thr_num == 0)
91
92 thread_info *tp = nullptr;
93 for (thread_info *it : inf->threads ())
94 if (it->per_inf_num == thr_num)
95 {
96 tp = it;
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
117 int default_inferior)
118{
119 init (tidlist, default_inferior);
120}
121
122/* See tid-parse.h. */
123
124void
125tid_range_parser::init (const char *tidlist, int default_inferior)
126{
128 m_cur_tok = tidlist;
129 m_inf_num = 0;
130 m_qualified = false;
131 m_default_inferior = default_inferior;
132}
133
134/* See tid-parse.h. */
135
136bool
138{
139 switch (m_state)
140 {
141 case STATE_INFERIOR:
142 /* Parsing is finished when at end of string or null string,
143 or we are not in a range and not in front of an integer, negative
144 integer, convenience var or negative convenience var. */
145 return (*m_cur_tok == '\0'
146 || !(isdigit (*m_cur_tok)
147 || *m_cur_tok == '$'
148 || *m_cur_tok == '*'));
150 case STATE_STAR_RANGE:
151 return m_range_parser.finished ();
152 }
153
154 gdb_assert_not_reached ("unhandled state");
155}
156
157/* See tid-parse.h. */
158
159const char *
161{
162 switch (m_state)
163 {
164 case STATE_INFERIOR:
165 return m_cur_tok;
167 case STATE_STAR_RANGE:
168 return m_range_parser.cur_tok ();
169 }
170
171 gdb_assert_not_reached ("unhandled state");
172}
173
174void
183
184/* See tid-parse.h. */
185
186bool
188{
189 return m_qualified;
190}
191
192/* Helper for tid_range_parser::get_tid and
193 tid_range_parser::get_tid_range. Return the next range if THR_END
194 is non-NULL, return a single thread ID otherwise. */
195
196bool
198 int *thr_start, int *thr_end)
199{
200 if (m_state == STATE_INFERIOR)
201 {
202 const char *p;
203 const char *space;
204
205 space = skip_to_space (m_cur_tok);
206
207 p = m_cur_tok;
208 while (p < space && *p != '.')
209 p++;
210 if (p < space)
211 {
212 const char *dot = p;
213
214 /* Parse number to the left of the dot. */
215 p = m_cur_tok;
217 if (m_inf_num == 0)
218 return 0;
219
220 m_qualified = true;
221 p = dot + 1;
222
223 if (isspace (*p))
224 return false;
225 }
226 else
227 {
229 m_qualified = false;
230 p = m_cur_tok;
231 }
232
234 if (p[0] == '*' && (p[1] == '\0' || isspace (p[1])))
235 {
236 /* Setup the number range parser to return numbers in the
237 whole [1,INT_MAX] range. */
238 m_range_parser.setup_range (1, INT_MAX, skip_spaces (p + 1));
240 }
241 else
243 }
244
245 *inf_num = m_inf_num;
246 *thr_start = m_range_parser.get_number ();
247 if (*thr_start < 0)
248 error (_("negative value: %s"), m_cur_tok);
249 if (*thr_start == 0)
250 {
252 return false;
253 }
254
255 /* If we successfully parsed a thread number or finished parsing a
256 thread range, switch back to assuming the next TID is
257 inferior-qualified. */
258 if (!m_range_parser.in_range ())
259 {
262
263 if (thr_end != NULL)
264 *thr_end = *thr_start;
265 }
266
267 /* If we're midway through a range, and the caller wants the end
268 value, return it and skip to the end of the range. */
269 if (thr_end != NULL
272 {
273 *thr_end = m_range_parser.end_value ();
274
275 skip_range ();
276 }
277
278 return (*inf_num != 0 && *thr_start != 0);
279}
280
281/* See tid-parse.h. */
282
283bool
285 int *thr_start, int *thr_end)
286{
287 gdb_assert (inf_num != NULL && thr_start != NULL && thr_end != NULL);
288
289 return get_tid_or_range (inf_num, thr_start, thr_end);
290}
291
292/* See tid-parse.h. */
293
294bool
295tid_range_parser::get_tid (int *inf_num, int *thr_num)
296{
297 gdb_assert (inf_num != NULL && thr_num != NULL);
298
299 return get_tid_or_range (inf_num, thr_num, NULL);
300}
301
302/* See tid-parse.h. */
303
304bool
309
310bool
315
316/* See tid-parse.h. */
317
318int
319tid_is_in_list (const char *list, int default_inferior,
320 int inf_num, int thr_num)
321{
322 if (list == NULL || *list == '\0')
323 return 1;
324
325 tid_range_parser parser (list, default_inferior);
326 if (parser.finished ())
328 while (!parser.finished ())
329 {
330 int tmp_inf, tmp_thr_start, tmp_thr_end;
331
332 if (!parser.get_tid_range (&tmp_inf, &tmp_thr_start, &tmp_thr_end))
334 if (tmp_inf == inf_num
335 && tmp_thr_start <= thr_num && thr_num <= tmp_thr_end)
336 return 1;
337 }
338 return 0;
339}
int num
Definition inferior.h:557
int end_value() const
Definition cli-utils.h:114
bool finished() const
Definition cli-utils.c:327
const char * cur_tok() const
Definition cli-utils.h:106
void init(const char *string)
Definition cli-utils.c:225
bool in_range() const
Definition cli-utils.h:110
void setup_range(int start_value, int end_value, const char *end_ptr)
Definition cli-utils.c:313
const char * cur_tok() const
Definition tid-parse.c:160
bool get_tid_or_range(int *inf_num, int *thr_start, int *thr_end)
Definition tid-parse.c:197
number_or_range_parser m_range_parser
Definition tid-parse.h:163
enum tid_range_parser::@187 m_state
bool in_thread_range() const
Definition tid-parse.c:311
bool tid_is_qualified() const
Definition tid-parse.c:187
bool finished() const
Definition tid-parse.c:137
bool get_tid_range(int *inf_num, int *thr_start, int *thr_end)
Definition tid-parse.c:284
void init(const char *tidlist, int default_inferior)
Definition tid-parse.c:125
const char * m_cur_tok
Definition tid-parse.h:159
bool get_tid(int *inf_num, int *thr_num)
Definition tid-parse.c:295
bool in_star_range() const
Definition tid-parse.c:305
int get_number_trailer(const char **pp, int trailer)
Definition cli-utils.c:81
int show_inferior_qualified_tids(void)
Definition thread.c:1458
struct inferior * current_inferior(void)
Definition inferior.c:55
struct inferior * find_inferior_id(int num)
Definition inferior.c:379
Definition gnu-nat.c:153
struct proc * threads
Definition gnu-nat.c:157
struct thread_info * parse_thread_id(const char *tidstr, const char **end)
Definition tid-parse.c:54
int tid_is_in_list(const char *list, int default_inferior, int inf_num, int thr_num)
Definition tid-parse.c:319
void ATTRIBUTE_NORETURN invalid_thread_id_error(const char *string)
Definition tid-parse.c:29
static int get_positive_number_trailer(const char **pp, int trailer, const char *string)
Definition tid-parse.c:41