3 Copyright (C) 2011-2018 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 /* See documentation in cli-utils.h. */
29 get_number_trailer (const char **pp, int trailer)
31 int retval = 0; /* default */
33 bool negative = false;
43 struct value *val = value_from_history_ref (p, &p);
45 if (val) /* Value history reference */
47 if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
48 retval = value_as_long (val);
51 printf_filtered (_("History value must have integer type.\n"));
55 else /* Convenience variable */
57 /* Internal variable. Make a copy of the name, so we can
58 null-terminate it to pass to lookup_internalvar(). */
60 const char *start = ++p;
63 while (isalnum (*p) || *p == '_')
65 varname = (char *) alloca (p - start + 1);
66 strncpy (varname, start, p - start);
67 varname[p - start] = '\0';
68 if (get_internalvar_integer (lookup_internalvar (varname), &val))
72 printf_filtered (_("Convenience variable must "
73 "have integer value.\n"));
81 while (*p >= '0' && *p <= '9')
84 /* There is no number here. (e.g. "cond a == b"). */
86 /* Skip non-numeric token. */
87 while (*p && !isspace((int) *p))
89 /* Return zero, which caller must interpret as error. */
95 if (!(isspace (*p) || *p == '\0' || *p == trailer))
97 /* Trailing junk: return 0 and let caller print error msg. */
98 while (!(isspace (*p) || *p == '\0' || *p == trailer))
104 return negative ? -retval : retval;
107 /* See documentation in cli-utils.h. */
110 get_number (const char **pp)
112 return get_number_trailer (pp, '\0');
115 /* See documentation in cli-utils.h. */
118 get_number (char **pp)
123 result = get_number_trailer (&p, '\0');
128 /* See documentation in cli-utils.h. */
130 number_or_range_parser::number_or_range_parser (const char *string)
135 /* See documentation in cli-utils.h. */
138 number_or_range_parser::init (const char *string)
147 /* See documentation in cli-utils.h. */
150 number_or_range_parser::get_number ()
154 /* All number-parsing has already been done. Return the next
155 integer value (one greater than the saved previous value).
156 Do not advance the token pointer until the end of range is
159 if (++m_last_retval == m_end_value)
161 /* End of range reached; advance token pointer. */
162 m_cur_tok = m_end_ptr;
166 else if (*m_cur_tok != '-')
168 /* Default case: state->m_cur_tok is pointing either to a solo
169 number, or to the first number of a range. */
170 m_last_retval = get_number_trailer (&m_cur_tok, '-');
171 /* If get_number_trailer has found a -, it might be the start
172 of a command option. So, do not parse a range if the - is
173 followed by an alpha. */
174 if (*m_cur_tok == '-' && !isalpha (*(m_cur_tok + 1)))
178 /* This is the start of a range (<number1> - <number2>).
179 Skip the '-', parse and remember the second number,
180 and also remember the end of the final token. */
183 m_end_ptr = skip_spaces (m_cur_tok + 1);
184 m_end_value = ::get_number (temp);
185 if (m_end_value < m_last_retval)
187 error (_("inverted range"));
189 else if (m_end_value == m_last_retval)
191 /* Degenerate range (number1 == number2). Advance the
192 token pointer so that the range will be treated as a
194 m_cur_tok = m_end_ptr;
202 if (isdigit (*(m_cur_tok + 1)))
203 error (_("negative value"));
204 if (*(m_cur_tok + 1) == '$')
206 /* Convenience variable. */
207 m_last_retval = ::get_number (&m_cur_tok);
208 if (m_last_retval < 0)
209 error (_("negative value"));
212 return m_last_retval;
215 /* See documentation in cli-utils.h. */
218 number_or_range_parser::setup_range (int start_value, int end_value,
221 gdb_assert (start_value > 0);
225 m_last_retval = start_value - 1;
226 m_end_value = end_value;
229 /* See documentation in cli-utils.h. */
232 number_or_range_parser::finished () const
234 /* Parsing is finished when at end of string or null string,
235 or we are not in a range and not in front of an integer, negative
236 integer, convenience var or negative convenience var. */
237 return (m_cur_tok == NULL || *m_cur_tok == '\0'
239 && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
240 && !(*m_cur_tok == '-'
241 && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
244 /* Accept a number and a string-form list of numbers such as is
245 accepted by get_number_or_range. Return TRUE if the number is
248 By definition, an empty list includes all numbers. This is to
249 be interpreted as typing a command such as "delete break" with
253 number_is_in_list (const char *list, int number)
255 if (list == NULL || *list == '\0')
258 number_or_range_parser parser (list);
260 if (parser.finished ())
261 error (_("Arguments must be numbers or '$' variables."));
262 while (!parser.finished ())
264 int gotnum = parser.get_number ();
267 error (_("Arguments must be numbers or '$' variables."));
268 if (gotnum == number)
274 /* See documentation in cli-utils.h. */
277 remove_trailing_whitespace (const char *start, const char *s)
279 while (s > start && isspace (*(s - 1)))
285 /* See documentation in cli-utils.h. */
288 extract_arg (const char **arg)
293 return std::string ();
295 /* Find the start of the argument. */
296 *arg = skip_spaces (*arg);
298 return std::string ();
301 /* Find the end of the argument. */
302 *arg = skip_to_space (*arg + 1);
305 return std::string ();
307 return std::string (result, *arg - result);
310 /* See documentation in cli-utils.h. */
313 extract_arg (char **arg)
315 const char *arg_const = *arg;
318 result = extract_arg (&arg_const);
319 *arg += arg_const - *arg;
323 /* See documentation in cli-utils.h. */
326 check_for_argument (const char **str, const char *arg, int arg_len)
328 if (strncmp (*str, arg, arg_len) == 0
329 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
337 /* See documentation in cli-utils.h. */
340 parse_flags (const char **str, const char *flags)
342 const char *p = skip_spaces (*str);
346 && (p[2] == '\0' || isspace (p[2])))
348 const char pf = p[1];
349 const char *f = flags;
355 *str = skip_spaces (p + 2);
356 return f - flags + 1;
365 /* See documentation in cli-utils.h. */
368 parse_flags_qcs (const char *which_command, const char **str,
371 switch (parse_flags (str, "qcs"))
382 flags->silent = true;
385 gdb_assert_not_reached ("int qcs flag out of bound");
388 if (flags->cont && flags->silent)
389 error (_("%s: -c and -s are mutually exclusive"), which_command);