MIPS: Fix microMIPS instruction size determination
[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->in_range)
138 {
139 /* All number-parsing has already been done. Return the next
140 integer value (one greater than the saved previous value).
141 Do not advance the token pointer until the end of range is
142 reached. */
143
144 if (++state->last_retval == state->end_value)
145 {
146 /* End of range reached; advance token pointer. */
147 state->string = state->end_ptr;
148 state->in_range = 0;
149 }
150 }
151 else if (*state->string != '-')
152 {
153 /* Default case: state->string is pointing either to a solo
154 number, or to the first number of a range. */
155 state->last_retval = get_number_trailer (&state->string, '-');
156 if (*state->string == '-')
157 {
158 const char **temp;
159
160 /* This is the start of a range (<number1> - <number2>).
161 Skip the '-', parse and remember the second number,
162 and also remember the end of the final token. */
163
164 temp = &state->end_ptr;
165 state->end_ptr = skip_spaces_const (state->string + 1);
166 state->end_value = get_number_const (temp);
167 if (state->end_value < state->last_retval)
168 {
169 error (_("inverted range"));
170 }
171 else if (state->end_value == state->last_retval)
172 {
173 /* Degenerate range (number1 == number2). Advance the
174 token pointer so that the range will be treated as a
175 single number. */
176 state->string = state->end_ptr;
177 }
178 else
179 state->in_range = 1;
180 }
181 }
182 else
183 error (_("negative value"));
184 state->finished = *state->string == '\0';
185 return state->last_retval;
186 }
187
188 /* See documentation in cli-utils.h. */
189
190 void
191 number_range_setup_range (struct get_number_or_range_state *state,
192 int start_value, int end_value, const char *end_ptr)
193 {
194 gdb_assert (start_value > 0);
195
196 state->in_range = 1;
197 state->end_ptr = end_ptr;
198 state->last_retval = start_value - 1;
199 state->end_value = end_value;
200 }
201
202 /* Accept a number and a string-form list of numbers such as is
203 accepted by get_number_or_range. Return TRUE if the number is
204 in the list.
205
206 By definition, an empty list includes all numbers. This is to
207 be interpreted as typing a command such as "delete break" with
208 no arguments. */
209
210 int
211 number_is_in_list (const char *list, int number)
212 {
213 struct get_number_or_range_state state;
214
215 if (list == NULL || *list == '\0')
216 return 1;
217
218 init_number_or_range (&state, list);
219 while (!state.finished)
220 {
221 int gotnum = get_number_or_range (&state);
222
223 if (gotnum == 0)
224 error (_("Args must be numbers or '$' variables."));
225 if (gotnum == number)
226 return 1;
227 }
228 return 0;
229 }
230
231 /* See documentation in cli-utils.h. */
232
233 char *
234 remove_trailing_whitespace (const char *start, char *s)
235 {
236 while (s > start && isspace (*(s - 1)))
237 --s;
238
239 return s;
240 }
241
242 /* See documentation in cli-utils.h. */
243
244 char *
245 extract_arg_const (const char **arg)
246 {
247 const char *result;
248
249 if (!*arg)
250 return NULL;
251
252 /* Find the start of the argument. */
253 *arg = skip_spaces_const (*arg);
254 if (!**arg)
255 return NULL;
256 result = *arg;
257
258 /* Find the end of the argument. */
259 *arg = skip_to_space_const (*arg + 1);
260
261 if (result == *arg)
262 return NULL;
263
264 return savestring (result, *arg - result);
265 }
266
267 /* See documentation in cli-utils.h. */
268
269 char *
270 extract_arg (char **arg)
271 {
272 const char *arg_const = *arg;
273 char *result;
274
275 result = extract_arg_const (&arg_const);
276 *arg += arg_const - *arg;
277 return result;
278 }
279
280 /* See documentation in cli-utils.h. */
281
282 int
283 check_for_argument (char **str, char *arg, int arg_len)
284 {
285 if (strncmp (*str, arg, arg_len) == 0
286 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
287 {
288 *str += arg_len;
289 return 1;
290 }
291 return 0;
292 }
This page took 0.0347 seconds and 4 git commands to generate.