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))
142 *args = skip_spaces (*args);
148 if (check_for_argument (args, "-t", 2))
150 *t_regexp = extract_arg_maybe_quoted (args);
151 *args = skip_spaces (*args);
155 if (check_for_argument (args, "-q", 2))
158 *args = skip_spaces (*args);
165 /* See documentation in cli-utils.h. */
168 report_unrecognized_option_error (const char *command, const char *args)
170 std::string option = extract_arg (&args);
172 error (_("Unrecognized option '%s' to %s command. "
173 "Try \"help %s\"."), option.c_str (),
177 /* See documentation in cli-utils.h. */
180 info_print_args_help (const char *prefix,
181 const char *entity_kind)
183 return xstrprintf (_("\
184 %sIf NAMEREGEXP is provided, only prints the %s whose name\n\
185 matches NAMEREGEXP.\n\
186 If -t TYPEREGEXP is provided, only prints the %s whose type\n\
187 matches TYPEREGEXP. Note that the matching is done with the type\n\
188 printed by the 'whatis' command.\n\
189 By default, the command might produce headers and/or messages indicating\n\
190 why no %s can be printed.\n\
191 The flag -q disables the production of these headers and messages."),
192 prefix, entity_kind, entity_kind, entity_kind);
195 /* See documentation in cli-utils.h. */
197 number_or_range_parser::number_or_range_parser (const char *string)
202 /* See documentation in cli-utils.h. */
205 number_or_range_parser::init (const char *string)
214 /* See documentation in cli-utils.h. */
217 number_or_range_parser::get_number ()
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
226 if (++m_last_retval == m_end_value)
228 /* End of range reached; advance token pointer. */
229 m_cur_tok = m_end_ptr;
233 else if (*m_cur_tok != '-')
235 /* Default case: state->m_cur_tok is pointing either to a solo
236 number, or to the first number of a range. */
237 m_last_retval = get_number_trailer (&m_cur_tok, '-');
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)))
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. */
250 m_end_ptr = skip_spaces (m_cur_tok + 1);
251 m_end_value = ::get_number (temp);
252 if (m_end_value < m_last_retval)
254 error (_("inverted range"));
256 else if (m_end_value == m_last_retval)
258 /* Degenerate range (number1 == number2). Advance the
259 token pointer so that the range will be treated as a
261 m_cur_tok = m_end_ptr;
269 if (isdigit (*(m_cur_tok + 1)))
270 error (_("negative value"));
271 if (*(m_cur_tok + 1) == '$')
273 /* Convenience variable. */
274 m_last_retval = ::get_number (&m_cur_tok);
275 if (m_last_retval < 0)
276 error (_("negative value"));
279 return m_last_retval;
282 /* See documentation in cli-utils.h. */
285 number_or_range_parser::setup_range (int start_value, int end_value,
288 gdb_assert (start_value > 0);
292 m_last_retval = start_value - 1;
293 m_end_value = end_value;
296 /* See documentation in cli-utils.h. */
299 number_or_range_parser::finished () const
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'
306 && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
307 && !(*m_cur_tok == '-'
308 && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
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
315 By definition, an empty list includes all numbers. This is to
316 be interpreted as typing a command such as "delete break" with
320 number_is_in_list (const char *list, int number)
322 if (list == NULL || *list == '\0')
325 number_or_range_parser parser (list);
327 if (parser.finished ())
328 error (_("Arguments must be numbers or '$' variables."));
329 while (!parser.finished ())
331 int gotnum = parser.get_number ();
334 error (_("Arguments must be numbers or '$' variables."));
335 if (gotnum == number)
341 /* See documentation in cli-utils.h. */
344 remove_trailing_whitespace (const char *start, const char *s)
346 while (s > start && isspace (*(s - 1)))
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. */
359 extract_arg_maybe_quoted (const char **arg)
363 bool bsquote = false;
365 const char *p = *arg;
367 /* Find the start of the argument. */
370 /* Parse p similarly to gdb_argv buildargv function. */
373 if (isspace (*p) && !squote && !dquote && !bsquote)
415 /* See documentation in cli-utils.h. */
418 extract_arg (const char **arg)
423 return std::string ();
425 /* Find the start of the argument. */
426 *arg = skip_spaces (*arg);
428 return std::string ();
431 /* Find the end of the argument. */
432 *arg = skip_to_space (*arg + 1);
435 return std::string ();
437 return std::string (result, *arg - result);
440 /* See documentation in cli-utils.h. */
443 extract_arg (char **arg)
445 const char *arg_const = *arg;
448 result = extract_arg (&arg_const);
449 *arg += arg_const - *arg;
453 /* See documentation in cli-utils.h. */
456 check_for_argument (const char **str, const char *arg, int arg_len)
458 if (strncmp (*str, arg, arg_len) == 0
459 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
467 /* See documentation in cli-utils.h. */
470 parse_flags (const char **str, const char *flags)
472 const char *p = skip_spaces (*str);
476 && (p[2] == '\0' || isspace (p[2])))
478 const char pf = p[1];
479 const char *f = flags;
485 *str = skip_spaces (p + 2);
486 return f - flags + 1;
495 /* See documentation in cli-utils.h. */
498 parse_flags_qcs (const char *which_command, const char **str,
501 switch (parse_flags (str, "qcs"))
512 flags->silent = true;
515 gdb_assert_not_reached ("int qcs flag out of bound");
518 if (flags->cont && flags->silent)
519 error (_("%s: -c and -s are mutually exclusive"), which_command);