Per-inferior/Inferior-qualified thread IDs
[deliverable/binutils-gdb.git] / gdb / cli / cli-utils.c
1 /* CLI utilities.
2
3 Copyright (C) 2011-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 "cli/cli-utils.h"
22 #include "value.h"
23
24 #include <ctype.h>
25
26 /* See documentation in cli-utils.h. */
27
28 int
29 get_number_trailer (const char **pp, int trailer)
30 {
31 int retval = 0; /* default */
32 const char *p = *pp;
33
34 if (*p == '$')
35 {
36 struct value *val = value_from_history_ref (p, &p);
37
38 if (val) /* Value history reference */
39 {
40 if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
41 retval = value_as_long (val);
42 else
43 {
44 printf_filtered (_("History value must have integer type.\n"));
45 retval = 0;
46 }
47 }
48 else /* Convenience variable */
49 {
50 /* Internal variable. Make a copy of the name, so we can
51 null-terminate it to pass to lookup_internalvar(). */
52 char *varname;
53 const char *start = ++p;
54 LONGEST val;
55
56 while (isalnum (*p) || *p == '_')
57 p++;
58 varname = (char *) alloca (p - start + 1);
59 strncpy (varname, start, p - start);
60 varname[p - start] = '\0';
61 if (get_internalvar_integer (lookup_internalvar (varname), &val))
62 retval = (int) val;
63 else
64 {
65 printf_filtered (_("Convenience variable must "
66 "have integer value.\n"));
67 retval = 0;
68 }
69 }
70 }
71 else
72 {
73 if (*p == '-')
74 ++p;
75 while (*p >= '0' && *p <= '9')
76 ++p;
77 if (p == *pp)
78 /* There is no number here. (e.g. "cond a == b"). */
79 {
80 /* Skip non-numeric token. */
81 while (*p && !isspace((int) *p))
82 ++p;
83 /* Return zero, which caller must interpret as error. */
84 retval = 0;
85 }
86 else
87 retval = atoi (*pp);
88 }
89 if (!(isspace (*p) || *p == '\0' || *p == trailer))
90 {
91 /* Trailing junk: return 0 and let caller print error msg. */
92 while (!(isspace (*p) || *p == '\0' || *p == trailer))
93 ++p;
94 retval = 0;
95 }
96 p = skip_spaces_const (p);
97 *pp = p;
98 return retval;
99 }
100
101 /* See documentation in cli-utils.h. */
102
103 int
104 get_number_const (const char **pp)
105 {
106 return get_number_trailer (pp, '\0');
107 }
108
109 /* See documentation in cli-utils.h. */
110
111 int
112 get_number (char **pp)
113 {
114 int result;
115 const char *p = *pp;
116
117 result = get_number_trailer (&p, '\0');
118 *pp = (char *) p;
119 return result;
120 }
121
122 /* See documentation in cli-utils.h. */
123
124 void
125 init_number_or_range (struct get_number_or_range_state *state,
126 const char *string)
127 {
128 memset (state, 0, sizeof (*state));
129 state->string = string;
130 }
131
132 /* See documentation in cli-utils.h. */
133
134 int
135 get_number_or_range (struct get_number_or_range_state *state)
136 {
137 if (*state->string != '-')
138 {
139 /* Default case: state->string is pointing either to a solo
140 number, or to the first number of a range. */
141 state->last_retval = get_number_trailer (&state->string, '-');
142 if (*state->string == '-')
143 {
144 const char **temp;
145
146 /* This is the start of a range (<number1> - <number2>).
147 Skip the '-', parse and remember the second number,
148 and also remember the end of the final token. */
149
150 temp = &state->end_ptr;
151 state->end_ptr = skip_spaces_const (state->string + 1);
152 state->end_value = get_number_const (temp);
153 if (state->end_value < state->last_retval)
154 {
155 error (_("inverted range"));
156 }
157 else if (state->end_value == state->last_retval)
158 {
159 /* Degenerate range (number1 == number2). Advance the
160 token pointer so that the range will be treated as a
161 single number. */
162 state->string = state->end_ptr;
163 }
164 else
165 state->in_range = 1;
166 }
167 }
168 else if (! state->in_range)
169 error (_("negative value"));
170 else
171 {
172 /* state->string points to the '-' that betokens a range. All
173 number-parsing has already been done. Return the next
174 integer value (one greater than the saved previous value).
175 Do not advance the token pointer until the end of range
176 is reached. */
177
178 if (++state->last_retval == state->end_value)
179 {
180 /* End of range reached; advance token pointer. */
181 state->string = state->end_ptr;
182 state->in_range = 0;
183 }
184 }
185 state->finished = *state->string == '\0';
186 return state->last_retval;
187 }
188
189 /* Accept a number and a string-form list of numbers such as is
190 accepted by get_number_or_range. Return TRUE if the number is
191 in the list.
192
193 By definition, an empty list includes all numbers. This is to
194 be interpreted as typing a command such as "delete break" with
195 no arguments. */
196
197 int
198 number_is_in_list (const char *list, int number)
199 {
200 struct get_number_or_range_state state;
201
202 if (list == NULL || *list == '\0')
203 return 1;
204
205 init_number_or_range (&state, list);
206 while (!state.finished)
207 {
208 int gotnum = get_number_or_range (&state);
209
210 if (gotnum == 0)
211 error (_("Args must be numbers or '$' variables."));
212 if (gotnum == number)
213 return 1;
214 }
215 return 0;
216 }
217
218 /* See documentation in cli-utils.h. */
219
220 char *
221 remove_trailing_whitespace (const char *start, char *s)
222 {
223 while (s > start && isspace (*(s - 1)))
224 --s;
225
226 return s;
227 }
228
229 /* See documentation in cli-utils.h. */
230
231 char *
232 extract_arg_const (const char **arg)
233 {
234 const char *result;
235
236 if (!*arg)
237 return NULL;
238
239 /* Find the start of the argument. */
240 *arg = skip_spaces_const (*arg);
241 if (!**arg)
242 return NULL;
243 result = *arg;
244
245 /* Find the end of the argument. */
246 *arg = skip_to_space_const (*arg + 1);
247
248 if (result == *arg)
249 return NULL;
250
251 return savestring (result, *arg - result);
252 }
253
254 /* See documentation in cli-utils.h. */
255
256 char *
257 extract_arg (char **arg)
258 {
259 const char *arg_const = *arg;
260 char *result;
261
262 result = extract_arg_const (&arg_const);
263 *arg += arg_const - *arg;
264 return result;
265 }
266
267 /* See documentation in cli-utils.h. */
268
269 int
270 check_for_argument (char **str, char *arg, int arg_len)
271 {
272 if (strncmp (*str, arg, arg_len) == 0
273 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
274 {
275 *str += arg_len;
276 return 1;
277 }
278 return 0;
279 }
This page took 0.049593 seconds and 4 git commands to generate.