3 Copyright (C) 2011-2019 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
21 #include "cli/cli-utils.h"
26 static std::string
extract_arg_maybe_quoted (const char **arg
);
28 /* See documentation in cli-utils.h. */
31 get_number_trailer (const char **pp
, int trailer
)
33 int retval
= 0; /* default */
35 bool negative
= false;
45 struct value
*val
= value_from_history_ref (p
, &p
);
47 if (val
) /* Value history reference */
49 if (TYPE_CODE (value_type (val
)) == TYPE_CODE_INT
)
50 retval
= value_as_long (val
);
53 printf_filtered (_("History value must have integer type.\n"));
57 else /* Convenience variable */
59 /* Internal variable. Make a copy of the name, so we can
60 null-terminate it to pass to lookup_internalvar(). */
62 const char *start
= ++p
;
65 while (isalnum (*p
) || *p
== '_')
67 varname
= (char *) alloca (p
- start
+ 1);
68 strncpy (varname
, start
, p
- start
);
69 varname
[p
- start
] = '\0';
70 if (get_internalvar_integer (lookup_internalvar (varname
),
72 retval
= (int) longest_val
;
75 printf_filtered (_("Convenience variable must "
76 "have integer value.\n"));
84 while (*p
>= '0' && *p
<= '9')
87 /* There is no number here. (e.g. "cond a == b"). */
89 /* Skip non-numeric token. */
90 while (*p
&& !isspace((int) *p
))
92 /* Return zero, which caller must interpret as error. */
98 if (!(isspace (*p
) || *p
== '\0' || *p
== trailer
))
100 /* Trailing junk: return 0 and let caller print error msg. */
101 while (!(isspace (*p
) || *p
== '\0' || *p
== trailer
))
107 return negative
? -retval
: retval
;
110 /* See documentation in cli-utils.h. */
113 get_number (const char **pp
)
115 return get_number_trailer (pp
, '\0');
118 /* See documentation in cli-utils.h. */
121 get_number (char **pp
)
126 result
= get_number_trailer (&p
, '\0');
131 /* See documentation in cli-utils.h. */
134 extract_info_print_args (const char **args
,
137 std::string
*t_regexp
)
139 /* Check for NAMEREGEXP or -- NAMEREGEXP. */
140 if (**args
!= '-' || check_for_argument (args
, "--", 2))
147 if (check_for_argument (args
, "-t", 2))
149 *t_regexp
= extract_arg_maybe_quoted (args
);
150 *args
= skip_spaces (*args
);
154 if (check_for_argument (args
, "-q", 2))
163 /* See documentation in cli-utils.h. */
166 report_unrecognized_option_error (const char *command
, const char *args
)
168 std::string option
= extract_arg (&args
);
170 error (_("Unrecognized option '%s' to %s command. "
171 "Try \"help %s\"."), option
.c_str (),
175 /* See documentation in cli-utils.h. */
178 info_print_args_help (const char *prefix
,
179 const char *entity_kind
)
181 return xstrprintf (_("\
182 %sIf NAMEREGEXP is provided, only prints the %s whose name\n\
183 matches NAMEREGEXP.\n\
184 If -t TYPEREGEXP is provided, only prints the %s whose type\n\
185 matches TYPEREGEXP. Note that the matching is done with the type\n\
186 printed by the 'whatis' command.\n\
187 By default, the command might produce headers and/or messages indicating\n\
188 why no %s can be printed.\n\
189 The flag -q disables the production of these headers and messages."),
190 prefix
, entity_kind
, entity_kind
, entity_kind
);
193 /* See documentation in cli-utils.h. */
195 number_or_range_parser::number_or_range_parser (const char *string
)
200 /* See documentation in cli-utils.h. */
203 number_or_range_parser::init (const char *string
)
212 /* See documentation in cli-utils.h. */
215 number_or_range_parser::get_number ()
219 /* All number-parsing has already been done. Return the next
220 integer value (one greater than the saved previous value).
221 Do not advance the token pointer until the end of range is
224 if (++m_last_retval
== m_end_value
)
226 /* End of range reached; advance token pointer. */
227 m_cur_tok
= m_end_ptr
;
231 else if (*m_cur_tok
!= '-')
233 /* Default case: state->m_cur_tok is pointing either to a solo
234 number, or to the first number of a range. */
235 m_last_retval
= get_number_trailer (&m_cur_tok
, '-');
236 /* If get_number_trailer has found a -, it might be the start
237 of a command option. So, do not parse a range if the - is
238 followed by an alpha. */
239 if (*m_cur_tok
== '-' && !isalpha (*(m_cur_tok
+ 1)))
243 /* This is the start of a range (<number1> - <number2>).
244 Skip the '-', parse and remember the second number,
245 and also remember the end of the final token. */
248 m_end_ptr
= skip_spaces (m_cur_tok
+ 1);
249 m_end_value
= ::get_number (temp
);
250 if (m_end_value
< m_last_retval
)
252 error (_("inverted range"));
254 else if (m_end_value
== m_last_retval
)
256 /* Degenerate range (number1 == number2). Advance the
257 token pointer so that the range will be treated as a
259 m_cur_tok
= m_end_ptr
;
267 if (isdigit (*(m_cur_tok
+ 1)))
268 error (_("negative value"));
269 if (*(m_cur_tok
+ 1) == '$')
271 /* Convenience variable. */
272 m_last_retval
= ::get_number (&m_cur_tok
);
273 if (m_last_retval
< 0)
274 error (_("negative value"));
277 return m_last_retval
;
280 /* See documentation in cli-utils.h. */
283 number_or_range_parser::setup_range (int start_value
, int end_value
,
286 gdb_assert (start_value
> 0);
290 m_last_retval
= start_value
- 1;
291 m_end_value
= end_value
;
294 /* See documentation in cli-utils.h. */
297 number_or_range_parser::finished () const
299 /* Parsing is finished when at end of string or null string,
300 or we are not in a range and not in front of an integer, negative
301 integer, convenience var or negative convenience var. */
302 return (m_cur_tok
== NULL
|| *m_cur_tok
== '\0'
304 && !(isdigit (*m_cur_tok
) || *m_cur_tok
== '$')
305 && !(*m_cur_tok
== '-'
306 && (isdigit (m_cur_tok
[1]) || m_cur_tok
[1] == '$'))));
309 /* Accept a number and a string-form list of numbers such as is
310 accepted by get_number_or_range. Return TRUE if the number is
313 By definition, an empty list includes all numbers. This is to
314 be interpreted as typing a command such as "delete break" with
318 number_is_in_list (const char *list
, int number
)
320 if (list
== NULL
|| *list
== '\0')
323 number_or_range_parser
parser (list
);
325 if (parser
.finished ())
326 error (_("Arguments must be numbers or '$' variables."));
327 while (!parser
.finished ())
329 int gotnum
= parser
.get_number ();
332 error (_("Arguments must be numbers or '$' variables."));
333 if (gotnum
== number
)
339 /* See documentation in cli-utils.h. */
342 remove_trailing_whitespace (const char *start
, const char *s
)
344 while (s
> start
&& isspace (*(s
- 1)))
350 /* A helper function to extract an argument from *ARG. An argument is
351 delimited by whitespace, but it can also be optionally quoted.
352 The quoting and special characters are handled similarly to
353 the parsing done by gdb_argv.
354 The return value is empty if no argument was found. */
357 extract_arg_maybe_quoted (const char **arg
)
361 bool bsquote
= false;
363 const char *p
= *arg
;
365 /* Find the start of the argument. */
368 /* Parse p similarly to gdb_argv buildargv function. */
371 if (isspace (*p
) && !squote
&& !dquote
&& !bsquote
)
413 /* See documentation in cli-utils.h. */
416 extract_arg (const char **arg
)
421 return std::string ();
423 /* Find the start of the argument. */
424 *arg
= skip_spaces (*arg
);
426 return std::string ();
429 /* Find the end of the argument. */
430 *arg
= skip_to_space (*arg
+ 1);
433 return std::string ();
435 return std::string (result
, *arg
- result
);
438 /* See documentation in cli-utils.h. */
441 extract_arg (char **arg
)
443 const char *arg_const
= *arg
;
446 result
= extract_arg (&arg_const
);
447 *arg
+= arg_const
- *arg
;
451 /* See documentation in cli-utils.h. */
454 check_for_argument (const char **str
, const char *arg
, int arg_len
)
456 if (strncmp (*str
, arg
, arg_len
) == 0
457 && ((*str
)[arg_len
] == '\0' || isspace ((*str
)[arg_len
])))
460 *str
= skip_spaces (*str
);
466 /* See documentation in cli-utils.h. */
469 parse_flags (const char **str
, const char *flags
)
471 const char *p
= skip_spaces (*str
);
475 && (p
[2] == '\0' || isspace (p
[2])))
477 const char pf
= p
[1];
478 const char *f
= flags
;
484 *str
= skip_spaces (p
+ 2);
485 return f
- flags
+ 1;
494 /* See documentation in cli-utils.h. */
497 parse_flags_qcs (const char *which_command
, const char **str
,
500 switch (parse_flags (str
, "qcs"))
511 flags
->silent
= true;
514 gdb_assert_not_reached ("int qcs flag out of bound");
517 if (flags
->cont
&& flags
->silent
)
518 error (_("%s: -c and -s are mutually exclusive"), which_command
);