MI: extract command completion logic from complete_command()
[deliverable/binutils-gdb.git] / gdb / cli / cli-utils.c
CommitLineData
e9cafbcc
TT
1/* CLI utilities.
2
42a4f53d 3 Copyright (C) 2011-2019 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
0d4cad90
PW
26static std::string extract_arg_maybe_quoted (const char **arg);
27
5d5658a1 28/* See documentation in cli-utils.h. */
e9cafbcc 29
5d5658a1 30int
e799154c 31get_number_trailer (const char **pp, int trailer)
e9cafbcc
TT
32{
33 int retval = 0; /* default */
e799154c 34 const char *p = *pp;
95e95a6d
PA
35 bool negative = false;
36
37 if (*p == '-')
38 {
39 ++p;
40 negative = true;
41 }
e9cafbcc
TT
42
43 if (*p == '$')
44 {
3bd0f5ef 45 struct value *val = value_from_history_ref (p, &p);
e9cafbcc 46
3bd0f5ef 47 if (val) /* Value history reference */
e9cafbcc 48 {
3bd0f5ef
MS
49 if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
50 retval = value_as_long (val);
51 else
52 {
2217da06 53 printf_filtered (_("History value must have integer type.\n"));
3bd0f5ef
MS
54 retval = 0;
55 }
56 }
57 else /* Convenience variable */
58 {
59 /* Internal variable. Make a copy of the name, so we can
60 null-terminate it to pass to lookup_internalvar(). */
61 char *varname;
e799154c 62 const char *start = ++p;
b926417a 63 LONGEST longest_val;
3bd0f5ef
MS
64
65 while (isalnum (*p) || *p == '_')
66 p++;
67 varname = (char *) alloca (p - start + 1);
68 strncpy (varname, start, p - start);
69 varname[p - start] = '\0';
b926417a
TT
70 if (get_internalvar_integer (lookup_internalvar (varname),
71 &longest_val))
72 retval = (int) longest_val;
3bd0f5ef
MS
73 else
74 {
75 printf_filtered (_("Convenience variable must "
76 "have integer value.\n"));
77 retval = 0;
78 }
e9cafbcc
TT
79 }
80 }
81 else
82 {
95e95a6d 83 const char *p1 = p;
e9cafbcc
TT
84 while (*p >= '0' && *p <= '9')
85 ++p;
95e95a6d 86 if (p == p1)
e9cafbcc
TT
87 /* There is no number here. (e.g. "cond a == b"). */
88 {
89 /* Skip non-numeric token. */
90 while (*p && !isspace((int) *p))
91 ++p;
92 /* Return zero, which caller must interpret as error. */
93 retval = 0;
94 }
95 else
95e95a6d 96 retval = atoi (p1);
e9cafbcc
TT
97 }
98 if (!(isspace (*p) || *p == '\0' || *p == trailer))
99 {
100 /* Trailing junk: return 0 and let caller print error msg. */
101 while (!(isspace (*p) || *p == '\0' || *p == trailer))
102 ++p;
103 retval = 0;
104 }
f1735a53 105 p = skip_spaces (p);
e9cafbcc 106 *pp = p;
95e95a6d 107 return negative ? -retval : retval;
e9cafbcc
TT
108}
109
110/* See documentation in cli-utils.h. */
111
112int
f1735a53 113get_number (const char **pp)
e9cafbcc
TT
114{
115 return get_number_trailer (pp, '\0');
116}
117
118/* See documentation in cli-utils.h. */
119
e799154c
TT
120int
121get_number (char **pp)
122{
123 int result;
124 const char *p = *pp;
125
126 result = get_number_trailer (&p, '\0');
127 *pp = (char *) p;
128 return result;
129}
130
131/* See documentation in cli-utils.h. */
132
0d4cad90
PW
133bool
134extract_info_print_args (const char **args,
135 bool *quiet,
136 std::string *regexp,
137 std::string *t_regexp)
138{
139 /* Check for NAMEREGEXP or -- NAMEREGEXP. */
140 if (**args != '-' || check_for_argument (args, "--", 2))
141 {
142 *args = skip_spaces (*args);
143 *regexp = *args;
144 *args = NULL;
145 return true;
146 }
147
148 if (check_for_argument (args, "-t", 2))
149 {
150 *t_regexp = extract_arg_maybe_quoted (args);
151 *args = skip_spaces (*args);
152 return true;
153 }
154
155 if (check_for_argument (args, "-q", 2))
156 {
157 *quiet = true;
158 *args = skip_spaces (*args);
159 return true;
160 }
161
162 return false;
163}
164
165/* See documentation in cli-utils.h. */
166
167void
168report_unrecognized_option_error (const char *command, const char *args)
169{
170 std::string option = extract_arg (&args);
171
172 error (_("Unrecognized option '%s' to %s command. "
173 "Try \"help %s\"."), option.c_str (),
174 command, command);
175}
176
177/* See documentation in cli-utils.h. */
178
179const char *
180info_print_args_help (const char *prefix,
181 const char *entity_kind)
182{
183 return xstrprintf (_("\
184%sIf NAMEREGEXP is provided, only prints the %s whose name\n\
185matches NAMEREGEXP.\n\
186If -t TYPEREGEXP is provided, only prints the %s whose type\n\
187matches TYPEREGEXP. Note that the matching is done with the type\n\
188printed by the 'whatis' command.\n\
189By default, the command might produce headers and/or messages indicating\n\
190why no %s can be printed.\n\
191The flag -q disables the production of these headers and messages."),
192 prefix, entity_kind, entity_kind, entity_kind);
193}
194
195/* See documentation in cli-utils.h. */
196
bfd28288
PA
197number_or_range_parser::number_or_range_parser (const char *string)
198{
199 init (string);
200}
201
202/* See documentation in cli-utils.h. */
203
197f0a60 204void
bfd28288 205number_or_range_parser::init (const char *string)
e9cafbcc 206{
bfd28288
PA
207 m_cur_tok = string;
208 m_last_retval = 0;
209 m_end_value = 0;
210 m_end_ptr = NULL;
211 m_in_range = false;
197f0a60
TT
212}
213
214/* See documentation in cli-utils.h. */
e9cafbcc 215
197f0a60 216int
bfd28288 217number_or_range_parser::get_number ()
197f0a60 218{
bfd28288 219 if (m_in_range)
71ef29a8
PA
220 {
221 /* All number-parsing has already been done. Return the next
222 integer value (one greater than the saved previous value).
223 Do not advance the token pointer until the end of range is
224 reached. */
225
bfd28288 226 if (++m_last_retval == m_end_value)
71ef29a8
PA
227 {
228 /* End of range reached; advance token pointer. */
bfd28288
PA
229 m_cur_tok = m_end_ptr;
230 m_in_range = false;
71ef29a8
PA
231 }
232 }
bfd28288 233 else if (*m_cur_tok != '-')
e9cafbcc 234 {
bfd28288 235 /* Default case: state->m_cur_tok is pointing either to a solo
197f0a60 236 number, or to the first number of a range. */
bfd28288 237 m_last_retval = get_number_trailer (&m_cur_tok, '-');
529c08b2
PW
238 /* If get_number_trailer has found a -, it might be the start
239 of a command option. So, do not parse a range if the - is
240 followed by an alpha. */
241 if (*m_cur_tok == '-' && !isalpha (*(m_cur_tok + 1)))
e9cafbcc 242 {
e799154c 243 const char **temp;
e9cafbcc
TT
244
245 /* This is the start of a range (<number1> - <number2>).
246 Skip the '-', parse and remember the second number,
247 and also remember the end of the final token. */
248
bfd28288 249 temp = &m_end_ptr;
f1735a53
TT
250 m_end_ptr = skip_spaces (m_cur_tok + 1);
251 m_end_value = ::get_number (temp);
bfd28288 252 if (m_end_value < m_last_retval)
e9cafbcc
TT
253 {
254 error (_("inverted range"));
255 }
bfd28288 256 else if (m_end_value == m_last_retval)
e9cafbcc
TT
257 {
258 /* Degenerate range (number1 == number2). Advance the
259 token pointer so that the range will be treated as a
bfd28288
PA
260 single number. */
261 m_cur_tok = m_end_ptr;
e9cafbcc
TT
262 }
263 else
bfd28288 264 m_in_range = true;
e9cafbcc
TT
265 }
266 }
e9cafbcc 267 else
529c08b2
PW
268 {
269 if (isdigit (*(m_cur_tok + 1)))
270 error (_("negative value"));
271 if (*(m_cur_tok + 1) == '$')
272 {
273 /* Convenience variable. */
274 m_last_retval = ::get_number (&m_cur_tok);
275 if (m_last_retval < 0)
276 error (_("negative value"));
277 }
278 }
bfd28288 279 return m_last_retval;
e9cafbcc
TT
280}
281
71ef29a8
PA
282/* See documentation in cli-utils.h. */
283
284void
bfd28288
PA
285number_or_range_parser::setup_range (int start_value, int end_value,
286 const char *end_ptr)
71ef29a8
PA
287{
288 gdb_assert (start_value > 0);
289
bfd28288
PA
290 m_in_range = true;
291 m_end_ptr = end_ptr;
292 m_last_retval = start_value - 1;
293 m_end_value = end_value;
71ef29a8
PA
294}
295
529c08b2
PW
296/* See documentation in cli-utils.h. */
297
298bool
299number_or_range_parser::finished () const
300{
301 /* Parsing is finished when at end of string or null string,
302 or we are not in a range and not in front of an integer, negative
303 integer, convenience var or negative convenience var. */
304 return (m_cur_tok == NULL || *m_cur_tok == '\0'
305 || (!m_in_range
306 && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
307 && !(*m_cur_tok == '-'
308 && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
309}
310
aea5b279
MS
311/* Accept a number and a string-form list of numbers such as is
312 accepted by get_number_or_range. Return TRUE if the number is
313 in the list.
314
315 By definition, an empty list includes all numbers. This is to
316 be interpreted as typing a command such as "delete break" with
317 no arguments. */
318
319int
e799154c 320number_is_in_list (const char *list, int number)
aea5b279
MS
321{
322 if (list == NULL || *list == '\0')
323 return 1;
324
bfd28288 325 number_or_range_parser parser (list);
529c08b2
PW
326
327 if (parser.finished ())
328 error (_("Arguments must be numbers or '$' variables."));
bfd28288 329 while (!parser.finished ())
298f437a 330 {
bfd28288 331 int gotnum = parser.get_number ();
aea5b279 332
298f437a 333 if (gotnum == 0)
529c08b2 334 error (_("Arguments must be numbers or '$' variables."));
298f437a
MS
335 if (gotnum == number)
336 return 1;
337 }
aea5b279
MS
338 return 0;
339}
340
e9cafbcc
TT
341/* See documentation in cli-utils.h. */
342
63160a43
PA
343const char *
344remove_trailing_whitespace (const char *start, const char *s)
c00f8484
KS
345{
346 while (s > start && isspace (*(s - 1)))
347 --s;
348
349 return s;
350}
55aa24fb 351
0d4cad90
PW
352/* A helper function to extract an argument from *ARG. An argument is
353 delimited by whitespace, but it can also be optionally quoted.
354 The quoting and special characters are handled similarly to
355 the parsing done by gdb_argv.
356 The return value is empty if no argument was found. */
357
358static std::string
359extract_arg_maybe_quoted (const char **arg)
360{
361 bool squote = false;
362 bool dquote = false;
363 bool bsquote = false;
364 std::string result;
365 const char *p = *arg;
366
367 /* Find the start of the argument. */
368 p = skip_spaces (p);
369
370 /* Parse p similarly to gdb_argv buildargv function. */
371 while (*p != '\0')
372 {
373 if (isspace (*p) && !squote && !dquote && !bsquote)
374 break;
375 else
376 {
377 if (bsquote)
378 {
379 bsquote = false;
380 result += *p;
381 }
382 else if (*p == '\\')
383 bsquote = true;
384 else if (squote)
385 {
386 if (*p == '\'')
387 squote = false;
388 else
389 result += *p;
390 }
391 else if (dquote)
392 {
393 if (*p == '"')
394 dquote = false;
395 else
396 result += *p;
397 }
398 else
399 {
400 if (*p == '\'')
401 squote = true;
402 else if (*p == '"')
403 dquote = true;
404 else
405 result += *p;
406 }
407 p++;
408 }
409 }
410
411 *arg = p;
412 return result;
413}
414
55aa24fb
SDJ
415/* See documentation in cli-utils.h. */
416
cb791d59 417std::string
f1735a53 418extract_arg (const char **arg)
55aa24fb 419{
b5be8ce0 420 const char *result;
55aa24fb
SDJ
421
422 if (!*arg)
cb791d59 423 return std::string ();
55aa24fb
SDJ
424
425 /* Find the start of the argument. */
f1735a53 426 *arg = skip_spaces (*arg);
55aa24fb 427 if (!**arg)
cb791d59 428 return std::string ();
55aa24fb
SDJ
429 result = *arg;
430
431 /* Find the end of the argument. */
f1735a53 432 *arg = skip_to_space (*arg + 1);
55aa24fb
SDJ
433
434 if (result == *arg)
cb791d59 435 return std::string ();
55aa24fb 436
cb791d59 437 return std::string (result, *arg - result);
b5be8ce0
JB
438}
439
440/* See documentation in cli-utils.h. */
441
cb791d59 442std::string
b5be8ce0
JB
443extract_arg (char **arg)
444{
445 const char *arg_const = *arg;
cb791d59 446 std::string result;
55aa24fb 447
f1735a53 448 result = extract_arg (&arg_const);
b5be8ce0
JB
449 *arg += arg_const - *arg;
450 return result;
55aa24fb 451}
e6f0bce7
HZ
452
453/* See documentation in cli-utils.h. */
454
455int
63160a43 456check_for_argument (const char **str, const char *arg, int arg_len)
e6f0bce7
HZ
457{
458 if (strncmp (*str, arg, arg_len) == 0
459 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
460 {
461 *str += arg_len;
462 return 1;
463 }
464 return 0;
465}
529c08b2
PW
466
467/* See documentation in cli-utils.h. */
468
469int
470parse_flags (const char **str, const char *flags)
471{
472 const char *p = skip_spaces (*str);
473
474 if (p[0] == '-'
475 && isalpha (p[1])
476 && (p[2] == '\0' || isspace (p[2])))
477 {
478 const char pf = p[1];
479 const char *f = flags;
480
481 while (*f != '\0')
482 {
483 if (*f == pf)
484 {
485 *str = skip_spaces (p + 2);
486 return f - flags + 1;
487 }
488 f++;
489 }
490 }
491
492 return 0;
493}
494
495/* See documentation in cli-utils.h. */
496
497bool
498parse_flags_qcs (const char *which_command, const char **str,
499 qcs_flags *flags)
500{
501 switch (parse_flags (str, "qcs"))
502 {
503 case 0:
504 return false;
505 case 1:
506 flags->quiet = true;
507 break;
508 case 2:
509 flags->cont = true;
510 break;
511 case 3:
512 flags->silent = true;
513 break;
514 default:
515 gdb_assert_not_reached ("int qcs flag out of bound");
516 }
517
518 if (flags->cont && flags->silent)
519 error (_("%s: -c and -s are mutually exclusive"), which_command);
520
521 return true;
522}
This page took 0.568313 seconds and 4 git commands to generate.