Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / cli / cli-utils.c
CommitLineData
e9cafbcc
TT
1/* CLI utilities.
2
e2882c85 3 Copyright (C) 2011-2018 Free Software Foundation, Inc.
e9cafbcc
TT
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"
e9cafbcc
TT
22#include "value.h"
23
24#include <ctype.h>
25
5d5658a1 26/* See documentation in cli-utils.h. */
e9cafbcc 27
5d5658a1 28int
e799154c 29get_number_trailer (const char **pp, int trailer)
e9cafbcc
TT
30{
31 int retval = 0; /* default */
e799154c 32 const char *p = *pp;
95e95a6d
PA
33 bool negative = false;
34
35 if (*p == '-')
36 {
37 ++p;
38 negative = true;
39 }
e9cafbcc
TT
40
41 if (*p == '$')
42 {
3bd0f5ef 43 struct value *val = value_from_history_ref (p, &p);
e9cafbcc 44
3bd0f5ef 45 if (val) /* Value history reference */
e9cafbcc 46 {
3bd0f5ef
MS
47 if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
48 retval = value_as_long (val);
49 else
50 {
2217da06 51 printf_filtered (_("History value must have integer type.\n"));
3bd0f5ef
MS
52 retval = 0;
53 }
54 }
55 else /* Convenience variable */
56 {
57 /* Internal variable. Make a copy of the name, so we can
58 null-terminate it to pass to lookup_internalvar(). */
59 char *varname;
e799154c 60 const char *start = ++p;
b926417a 61 LONGEST longest_val;
3bd0f5ef
MS
62
63 while (isalnum (*p) || *p == '_')
64 p++;
65 varname = (char *) alloca (p - start + 1);
66 strncpy (varname, start, p - start);
67 varname[p - start] = '\0';
b926417a
TT
68 if (get_internalvar_integer (lookup_internalvar (varname),
69 &longest_val))
70 retval = (int) longest_val;
3bd0f5ef
MS
71 else
72 {
73 printf_filtered (_("Convenience variable must "
74 "have integer value.\n"));
75 retval = 0;
76 }
e9cafbcc
TT
77 }
78 }
79 else
80 {
95e95a6d 81 const char *p1 = p;
e9cafbcc
TT
82 while (*p >= '0' && *p <= '9')
83 ++p;
95e95a6d 84 if (p == p1)
e9cafbcc
TT
85 /* There is no number here. (e.g. "cond a == b"). */
86 {
87 /* Skip non-numeric token. */
88 while (*p && !isspace((int) *p))
89 ++p;
90 /* Return zero, which caller must interpret as error. */
91 retval = 0;
92 }
93 else
95e95a6d 94 retval = atoi (p1);
e9cafbcc
TT
95 }
96 if (!(isspace (*p) || *p == '\0' || *p == trailer))
97 {
98 /* Trailing junk: return 0 and let caller print error msg. */
99 while (!(isspace (*p) || *p == '\0' || *p == trailer))
100 ++p;
101 retval = 0;
102 }
f1735a53 103 p = skip_spaces (p);
e9cafbcc 104 *pp = p;
95e95a6d 105 return negative ? -retval : retval;
e9cafbcc
TT
106}
107
108/* See documentation in cli-utils.h. */
109
110int
f1735a53 111get_number (const char **pp)
e9cafbcc
TT
112{
113 return get_number_trailer (pp, '\0');
114}
115
116/* See documentation in cli-utils.h. */
117
e799154c
TT
118int
119get_number (char **pp)
120{
121 int result;
122 const char *p = *pp;
123
124 result = get_number_trailer (&p, '\0');
125 *pp = (char *) p;
126 return result;
127}
128
129/* See documentation in cli-utils.h. */
130
bfd28288
PA
131number_or_range_parser::number_or_range_parser (const char *string)
132{
133 init (string);
134}
135
136/* See documentation in cli-utils.h. */
137
197f0a60 138void
bfd28288 139number_or_range_parser::init (const char *string)
e9cafbcc 140{
bfd28288
PA
141 m_cur_tok = string;
142 m_last_retval = 0;
143 m_end_value = 0;
144 m_end_ptr = NULL;
145 m_in_range = false;
197f0a60
TT
146}
147
148/* See documentation in cli-utils.h. */
e9cafbcc 149
197f0a60 150int
bfd28288 151number_or_range_parser::get_number ()
197f0a60 152{
bfd28288 153 if (m_in_range)
71ef29a8
PA
154 {
155 /* All number-parsing has already been done. Return the next
156 integer value (one greater than the saved previous value).
157 Do not advance the token pointer until the end of range is
158 reached. */
159
bfd28288 160 if (++m_last_retval == m_end_value)
71ef29a8
PA
161 {
162 /* End of range reached; advance token pointer. */
bfd28288
PA
163 m_cur_tok = m_end_ptr;
164 m_in_range = false;
71ef29a8
PA
165 }
166 }
bfd28288 167 else if (*m_cur_tok != '-')
e9cafbcc 168 {
bfd28288 169 /* Default case: state->m_cur_tok is pointing either to a solo
197f0a60 170 number, or to the first number of a range. */
bfd28288 171 m_last_retval = get_number_trailer (&m_cur_tok, '-');
529c08b2
PW
172 /* If get_number_trailer has found a -, it might be the start
173 of a command option. So, do not parse a range if the - is
174 followed by an alpha. */
175 if (*m_cur_tok == '-' && !isalpha (*(m_cur_tok + 1)))
e9cafbcc 176 {
e799154c 177 const char **temp;
e9cafbcc
TT
178
179 /* This is the start of a range (<number1> - <number2>).
180 Skip the '-', parse and remember the second number,
181 and also remember the end of the final token. */
182
bfd28288 183 temp = &m_end_ptr;
f1735a53
TT
184 m_end_ptr = skip_spaces (m_cur_tok + 1);
185 m_end_value = ::get_number (temp);
bfd28288 186 if (m_end_value < m_last_retval)
e9cafbcc
TT
187 {
188 error (_("inverted range"));
189 }
bfd28288 190 else if (m_end_value == m_last_retval)
e9cafbcc
TT
191 {
192 /* Degenerate range (number1 == number2). Advance the
193 token pointer so that the range will be treated as a
bfd28288
PA
194 single number. */
195 m_cur_tok = m_end_ptr;
e9cafbcc
TT
196 }
197 else
bfd28288 198 m_in_range = true;
e9cafbcc
TT
199 }
200 }
e9cafbcc 201 else
529c08b2
PW
202 {
203 if (isdigit (*(m_cur_tok + 1)))
204 error (_("negative value"));
205 if (*(m_cur_tok + 1) == '$')
206 {
207 /* Convenience variable. */
208 m_last_retval = ::get_number (&m_cur_tok);
209 if (m_last_retval < 0)
210 error (_("negative value"));
211 }
212 }
bfd28288 213 return m_last_retval;
e9cafbcc
TT
214}
215
71ef29a8
PA
216/* See documentation in cli-utils.h. */
217
218void
bfd28288
PA
219number_or_range_parser::setup_range (int start_value, int end_value,
220 const char *end_ptr)
71ef29a8
PA
221{
222 gdb_assert (start_value > 0);
223
bfd28288
PA
224 m_in_range = true;
225 m_end_ptr = end_ptr;
226 m_last_retval = start_value - 1;
227 m_end_value = end_value;
71ef29a8
PA
228}
229
529c08b2
PW
230/* See documentation in cli-utils.h. */
231
232bool
233number_or_range_parser::finished () const
234{
235 /* Parsing is finished when at end of string or null string,
236 or we are not in a range and not in front of an integer, negative
237 integer, convenience var or negative convenience var. */
238 return (m_cur_tok == NULL || *m_cur_tok == '\0'
239 || (!m_in_range
240 && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
241 && !(*m_cur_tok == '-'
242 && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
243}
244
aea5b279
MS
245/* Accept a number and a string-form list of numbers such as is
246 accepted by get_number_or_range. Return TRUE if the number is
247 in the list.
248
249 By definition, an empty list includes all numbers. This is to
250 be interpreted as typing a command such as "delete break" with
251 no arguments. */
252
253int
e799154c 254number_is_in_list (const char *list, int number)
aea5b279
MS
255{
256 if (list == NULL || *list == '\0')
257 return 1;
258
bfd28288 259 number_or_range_parser parser (list);
529c08b2
PW
260
261 if (parser.finished ())
262 error (_("Arguments must be numbers or '$' variables."));
bfd28288 263 while (!parser.finished ())
298f437a 264 {
bfd28288 265 int gotnum = parser.get_number ();
aea5b279 266
298f437a 267 if (gotnum == 0)
529c08b2 268 error (_("Arguments must be numbers or '$' variables."));
298f437a
MS
269 if (gotnum == number)
270 return 1;
271 }
aea5b279
MS
272 return 0;
273}
274
e9cafbcc
TT
275/* See documentation in cli-utils.h. */
276
63160a43
PA
277const char *
278remove_trailing_whitespace (const char *start, const char *s)
c00f8484
KS
279{
280 while (s > start && isspace (*(s - 1)))
281 --s;
282
283 return s;
284}
55aa24fb
SDJ
285
286/* See documentation in cli-utils.h. */
287
cb791d59 288std::string
f1735a53 289extract_arg (const char **arg)
55aa24fb 290{
b5be8ce0 291 const char *result;
55aa24fb
SDJ
292
293 if (!*arg)
cb791d59 294 return std::string ();
55aa24fb
SDJ
295
296 /* Find the start of the argument. */
f1735a53 297 *arg = skip_spaces (*arg);
55aa24fb 298 if (!**arg)
cb791d59 299 return std::string ();
55aa24fb
SDJ
300 result = *arg;
301
302 /* Find the end of the argument. */
f1735a53 303 *arg = skip_to_space (*arg + 1);
55aa24fb
SDJ
304
305 if (result == *arg)
cb791d59 306 return std::string ();
55aa24fb 307
cb791d59 308 return std::string (result, *arg - result);
b5be8ce0
JB
309}
310
311/* See documentation in cli-utils.h. */
312
cb791d59 313std::string
b5be8ce0
JB
314extract_arg (char **arg)
315{
316 const char *arg_const = *arg;
cb791d59 317 std::string result;
55aa24fb 318
f1735a53 319 result = extract_arg (&arg_const);
b5be8ce0
JB
320 *arg += arg_const - *arg;
321 return result;
55aa24fb 322}
e6f0bce7
HZ
323
324/* See documentation in cli-utils.h. */
325
326int
63160a43 327check_for_argument (const char **str, const char *arg, int arg_len)
e6f0bce7
HZ
328{
329 if (strncmp (*str, arg, arg_len) == 0
330 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
331 {
332 *str += arg_len;
333 return 1;
334 }
335 return 0;
336}
529c08b2
PW
337
338/* See documentation in cli-utils.h. */
339
340int
341parse_flags (const char **str, const char *flags)
342{
343 const char *p = skip_spaces (*str);
344
345 if (p[0] == '-'
346 && isalpha (p[1])
347 && (p[2] == '\0' || isspace (p[2])))
348 {
349 const char pf = p[1];
350 const char *f = flags;
351
352 while (*f != '\0')
353 {
354 if (*f == pf)
355 {
356 *str = skip_spaces (p + 2);
357 return f - flags + 1;
358 }
359 f++;
360 }
361 }
362
363 return 0;
364}
365
366/* See documentation in cli-utils.h. */
367
368bool
369parse_flags_qcs (const char *which_command, const char **str,
370 qcs_flags *flags)
371{
372 switch (parse_flags (str, "qcs"))
373 {
374 case 0:
375 return false;
376 case 1:
377 flags->quiet = true;
378 break;
379 case 2:
380 flags->cont = true;
381 break;
382 case 3:
383 flags->silent = true;
384 break;
385 default:
386 gdb_assert_not_reached ("int qcs flag out of bound");
387 }
388
389 if (flags->cont && flags->silent)
390 error (_("%s: -c and -s are mutually exclusive"), which_command);
391
392 return true;
393}
This page took 0.544366 seconds and 4 git commands to generate.