GDB (xrefs)
/tmp/gdb-8.1/gdb/tid-parse.c
Go to the documentation of this file.
1 /* TID parsing for GDB, the GNU debugger.
2 
3  Copyright (C) 2015-2018 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 
28 void ATTRIBUTE_NORETURN
29 invalid_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 
40 static int
41 get_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 
53 struct thread_info *
54 parse_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;
71  inf_num = get_positive_number_trailer (&p1, '.', number);
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 
89  thr_num = get_positive_number_trailer (&p1, 0, number);
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 
117  int default_inferior)
118 {
119  init (tidlist, default_inferior);
120 }
121 
122 /* See tid-parse.h. */
123 
124 void
125 tid_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 
136 bool
138 {
139  switch (m_state)
140  {
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 ();
146  }
147 
148  gdb_assert_not_reached (_("unhandled state"));
149 }
150 
151 /* See tid-parse.h. */
152 
153 const char *
155 {
156  switch (m_state)
157  {
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 ();
163  }
164 
165  gdb_assert_not_reached (_("unhandled state"));
166 }
167 
168 void
170 {
172  || m_state == STATE_STAR_RANGE);
173 
176 }
177 
178 /* See tid-parse.h. */
179 
180 bool
182 {
183  return m_qualified;
184 }
185 
186 /* Helper for tid_range_parser::get_tid and
187  tid_range_parser::get_tid_range. Return the next range if THR_END
188  is non-NULL, return a single thread ID otherwise. */
189 
190 bool
192  int *thr_start, int *thr_end)
193 {
194  if (m_state == STATE_INFERIOR)
195  {
196  const char *p;
197  const char *space;
198 
199  space = skip_to_space (m_cur_tok);
200 
201  p = m_cur_tok;
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. */
209  p = m_cur_tok;
211  if (m_inf_num == 0)
212  return 0;
213 
214  m_qualified = true;
215  p = dot + 1;
216 
217  if (isspace (*p))
218  return false;
219  }
220  else
221  {
223  m_qualified = false;
224  p = m_cur_tok;
225  }
226 
227  m_range_parser.init (p);
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. */
234  }
235  else
237  }
238 
239  *inf_num = m_inf_num;
240  *thr_start = m_range_parser.get_number ();
241  if (*thr_start < 0)
242  error (_("negative value: %s"), m_cur_tok);
243  if (*thr_start == 0)
244  {
246  return false;
247  }
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. */
252  if (!m_range_parser.in_range ())
253  {
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. */
263  if (thr_end != NULL
265  || m_state == STATE_STAR_RANGE))
266  {
267  *thr_end = m_range_parser.end_value ();
268 
269  skip_range ();
270  }
271 
272  return (*inf_num != 0 && *thr_start != 0);
273 }
274 
275 /* See tid-parse.h. */
276 
277 bool
279  int *thr_start, int *thr_end)
280 {
281  gdb_assert (inf_num != NULL && thr_start != NULL && thr_end != NULL);
282 
283  return get_tid_or_range (inf_num, thr_start, thr_end);
284 }
285 
286 /* See tid-parse.h. */
287 
288 bool
289 tid_range_parser::get_tid (int *inf_num, int *thr_num)
290 {
291  gdb_assert (inf_num != NULL && thr_num != NULL);
292 
293  return get_tid_or_range (inf_num, thr_num, NULL);
294 }
295 
296 /* See tid-parse.h. */
297 
298 bool
300 {
301  return m_state == STATE_STAR_RANGE;
302 }
303 
304 /* See gdbthread.h. */
305 
306 int
307 tid_is_in_list (const char *list, int default_inferior,
308  int inf_num, int thr_num)
309 {
310  if (list == NULL || *list == '\0')
311  return 1;
312 
313  tid_range_parser parser (list, default_inferior);
314  while (!parser.finished ())
315  {
316  int tmp_inf, tmp_thr_start, tmp_thr_end;
317 
318  if (!parser.get_tid_range (&tmp_inf, &tmp_thr_start, &tmp_thr_end))
319  invalid_thread_id_error (parser.cur_tok ());
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 }
int show_inferior_qualified_tids(void)
Definition: thread.c:1594
int ptid_get_pid(const ptid_t &ptid)
Definition: ptid.c:47
int m_default_inferior
Definition: tid-parse.h:171
#define INT_MAX
Definition: defs.h:477
void ATTRIBUTE_NORETURN invalid_thread_id_error(const char *string)
Definition: tid-parse.c:29
bool get_tid(int *inf_num, int *thr_num)
Definition: tid-parse.c:289
bool tid_is_qualified() const
Definition: tid-parse.c:181
int tid_is_in_list(const char *list, int default_inferior, int inf_num, int thr_num)
Definition: tid-parse.c:307
char * skip_spaces(char *chp)
Definition: common-utils.c:337
#define _(String)
Definition: gdb_locale.h:35
enum tid_range_parser::@176 m_state
bool get_tid_or_range(int *inf_num, int *thr_start, int *thr_end)
Definition: tid-parse.c:191
bool finished() const
Definition: tid-parse.c:137
const char * cur_tok() const
Definition: cli-utils.h:83
int per_inf_num
Definition: gdbthread.h:258
bool get_tid_range(int *inf_num, int *thr_start, int *thr_end)
Definition: tid-parse.c:278
const char * cur_tok() const
Definition: tid-parse.c:154
bool finished() const
Definition: cli-utils.h:78
int get_number_trailer(const char **pp, int trailer)
Definition: cli-utils.c:29
#define gdb_assert_not_reached(message)
Definition: gdb_assert.h:55
bool in_star_range() const
Definition: tid-parse.c:299
void setup_range(int start_value, int end_value, const char *end_ptr)
Definition: cli-utils.c:207
Definition: gnu-nat.c:174
const char * skip_to_space(const char *chp)
Definition: common-utils.c:361
ptid_t ptid
Definition: gdbthread.h:219
void init(const char *tidlist, int default_inferior)
Definition: tid-parse.c:125
int num
Definition: inferior.h:324
#define ALL_THREADS(T)
Definition: gdbthread.h:478
#define gdb_assert(expr)
Definition: gdb_assert.h:32
void init(const char *string)
Definition: cli-utils.c:138
struct thread_info * parse_thread_id(const char *tidstr, const char **end)
Definition: tid-parse.c:54
const char * m_cur_tok
Definition: tid-parse.h:156
int end_value() const
Definition: cli-utils.h:91
pid_t pid
Definition: gnu-nat.c:187
void skip_range()
Definition: tid-parse.c:169
struct inferior * find_inferior_id(int num)
Definition: inferior.c:290
struct inferior * current_inferior(void)
Definition: inferior.c:58
static int get_positive_number_trailer(const char **pp, int trailer, const char *string)
Definition: tid-parse.c:41
number_or_range_parser m_range_parser
Definition: tid-parse.h:160
bool in_range() const
Definition: cli-utils.h:87
void error(const char *fmt,...)
Definition: errors.c:38