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