Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / tid-parse.c
CommitLineData
5d5658a1
PA
1/* TID parsing for GDB, the GNU debugger.
2
3 Copyright (C) 2015-2016 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/* See tid-parse.h. */
35
36struct thread_info *
37parse_thread_id (const char *tidstr, const char **end)
38{
39 const char *number = tidstr;
40 const char *dot, *p1;
41 struct thread_info *tp;
42 struct inferior *inf;
43 int thr_num;
44 int explicit_inf_id = 0;
45
46 dot = strchr (number, '.');
47
48 if (dot != NULL)
49 {
50 /* Parse number to the left of the dot. */
51 int inf_num;
52
53 p1 = number;
54 inf_num = get_number_trailer (&p1, '.');
55 if (inf_num == 0)
56 invalid_thread_id_error (number);
57
58 inf = find_inferior_id (inf_num);
59 if (inf == NULL)
60 error (_("No inferior number '%d'"), inf_num);
61
62 explicit_inf_id = 1;
63 p1 = dot + 1;
64 }
65 else
66 {
67 inf = current_inferior ();
68
69 p1 = number;
70 }
71
72 thr_num = get_number_const (&p1);
73 if (thr_num == 0)
74 invalid_thread_id_error (number);
75
76 ALL_THREADS (tp)
77 {
78 if (ptid_get_pid (tp->ptid) == inf->pid
79 && tp->per_inf_num == thr_num)
80 break;
81 }
82
83 if (tp == NULL)
84 {
85 if (show_inferior_qualified_tids () || explicit_inf_id)
86 error (_("Unknown thread %d.%d."), inf->num, thr_num);
87 else
88 error (_("Unknown thread %d."), thr_num);
89 }
90
91 if (end != NULL)
92 *end = p1;
93
94 return tp;
95}
96
97/* See tid-parse.h. */
98
99void
100tid_range_parser_init (struct tid_range_parser *parser, const char *tidlist,
101 int default_inferior)
102{
103 parser->state = TID_RANGE_STATE_INFERIOR;
104 parser->string = tidlist;
105 parser->inf_num = 0;
106 parser->qualified = 0;
107 parser->default_inferior = default_inferior;
108}
109
110/* See tid-parse.h. */
111
112int
113tid_range_parser_finished (struct tid_range_parser *parser)
114{
115 switch (parser->state)
116 {
117 case TID_RANGE_STATE_INFERIOR:
118 return *parser->string == '\0';
119 case TID_RANGE_STATE_THREAD_RANGE:
120 return parser->range_parser.finished;
121 }
122
123 gdb_assert_not_reached (_("unhandled state"));
124}
125
126/* See tid-parse.h. */
127
128const char *
129tid_range_parser_string (struct tid_range_parser *parser)
130{
131 switch (parser->state)
132 {
133 case TID_RANGE_STATE_INFERIOR:
134 return parser->string;
135 case TID_RANGE_STATE_THREAD_RANGE:
136 return parser->range_parser.string;
137 }
138
139 gdb_assert_not_reached (_("unhandled state"));
140}
141
142/* See tid-parse.h. */
143
144void
145tid_range_parser_skip (struct tid_range_parser *parser)
146{
147 gdb_assert ((parser->state == TID_RANGE_STATE_THREAD_RANGE)
148 && parser->range_parser.in_range);
149
150 tid_range_parser_init (parser, parser->range_parser.end_ptr,
151 parser->default_inferior);
152}
153
154/* See tid-parse.h. */
155
156int
157tid_range_parser_qualified (struct tid_range_parser *parser)
158{
159 return parser->qualified;
160}
161
162/* Helper for tid_range_parser_get_tid and
163 tid_range_parser_get_tid_range. Return the next range if THR_END
164 is non-NULL, return a single thread ID otherwise. */
165
166static int
167get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
168 int *thr_start, int *thr_end)
169{
170 if (parser->state == TID_RANGE_STATE_INFERIOR)
171 {
172 const char *p;
173 const char *space;
174
175 space = skip_to_space (parser->string);
176
177 p = parser->string;
178 while (p < space && *p != '.')
179 p++;
180 if (p < space)
181 {
182 const char *dot = p;
183
184 /* Parse number to the left of the dot. */
185 p = parser->string;
186 parser->inf_num = get_number_trailer (&p, '.');
187 if (parser->inf_num == 0)
188 invalid_thread_id_error (parser->string);
189
190 parser->qualified = 1;
191 p = dot + 1;
192
193 if (isspace (*p))
194 invalid_thread_id_error (parser->string);
195 }
196 else
197 {
198 parser->inf_num = parser->default_inferior;
199 parser->qualified = 0;
200 p = parser->string;
201 }
202
203 init_number_or_range (&parser->range_parser, p);
204 parser->state = TID_RANGE_STATE_THREAD_RANGE;
205 }
206
207 *inf_num = parser->inf_num;
208 *thr_start = get_number_or_range (&parser->range_parser);
209 if (*thr_start == 0)
210 invalid_thread_id_error (parser->string);
211
212 /* If we successfully parsed a thread number or finished parsing a
213 thread range, switch back to assuming the next TID is
214 inferior-qualified. */
215 if (parser->range_parser.end_ptr == NULL
216 || parser->range_parser.string == parser->range_parser.end_ptr)
217 {
218 parser->state = TID_RANGE_STATE_INFERIOR;
219 parser->string = parser->range_parser.string;
220
221 if (thr_end != NULL)
222 *thr_end = *thr_start;
223 }
224
225 /* If we're midway through a range, and the caller wants the end
226 value, return it and skip to the end of the range. */
227 if (thr_end != NULL && parser->state == TID_RANGE_STATE_THREAD_RANGE)
228 {
229 *thr_end = parser->range_parser.end_value;
230 tid_range_parser_skip (parser);
231 }
232
233 return (*inf_num != 0 && *thr_start != 0);
234}
235
236/* See tid-parse.h. */
237
238int
239tid_range_parser_get_tid_range (struct tid_range_parser *parser, int *inf_num,
240 int *thr_start, int *thr_end)
241{
242 gdb_assert (inf_num != NULL && thr_start != NULL && thr_end != NULL);
243
244 return get_tid_or_range (parser, inf_num, thr_start, thr_end);
245}
246
247/* See tid-parse.h. */
248
249int
250tid_range_parser_get_tid (struct tid_range_parser *parser,
251 int *inf_num, int *thr_num)
252{
253 gdb_assert (inf_num != NULL && thr_num != NULL);
254
255 return get_tid_or_range (parser, inf_num, thr_num, NULL);
256}
257
258/* See tid-parse.h. */
259
260int
261tid_is_in_list (const char *list, int default_inferior,
262 int inf_num, int thr_num)
263{
264 struct tid_range_parser parser;
265
266 if (list == NULL || *list == '\0')
267 return 1;
268
269 tid_range_parser_init (&parser, list, default_inferior);
270 while (!tid_range_parser_finished (&parser))
271 {
272 int tmp_inf, tmp_thr_start, tmp_thr_end;
273
274 if (!tid_range_parser_get_tid_range (&parser, &tmp_inf,
275 &tmp_thr_start, &tmp_thr_end))
276 invalid_thread_id_error (parser.string);
277 if (tmp_inf == inf_num
278 && tmp_thr_start <= thr_num && thr_num <= tmp_thr_end)
279 return 1;
280 }
281 return 0;
282}
This page took 0.034793 seconds and 4 git commands to generate.