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