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),
70 retval = (int) longest_val;
73 printf_filtered (_("Convenience variable must "
74 "have integer value.\n"));
82 while (*p >= '0' && *p <= '9')
85 /* There is no number here. (e.g. "cond a == b"). */
87 /* Skip non-numeric token. */
88 while (*p && !isspace((int) *p))
90 /* Return zero, which caller must interpret as error. */
96 if (!(isspace (*p) || *p == '\0' || *p == trailer))
98 /* Trailing junk: return 0 and let caller print error msg. */
99 while (!(isspace (*p) || *p == '\0' || *p == trailer))
105 return negative ? -retval : retval;
108 /* See documentation in cli-utils.h. */
111 get_number (const char **pp)
113 return get_number_trailer (pp, '\0');
116 /* See documentation in cli-utils.h. */
119 get_number (char **pp)
124 result = get_number_trailer (&p, '\0');
129 /* See documentation in cli-utils.h. */
131 number_or_range_parser::number_or_range_parser (const char *string)
136 /* See documentation in cli-utils.h. */
139 number_or_range_parser::init (const char *string)
148 /* See documentation in cli-utils.h. */
151 number_or_range_parser::get_number ()
155 /* All number-parsing has already been done. Return the next
156 integer value (one greater than the saved previous value).
157 Do not advance the token pointer until the end of range is
160 if (++m_last_retval == m_end_value)
162 /* End of range reached; advance token pointer. */
163 m_cur_tok = m_end_ptr;
167 else if (*m_cur_tok != '-')
169 /* Default case: state->m_cur_tok is pointing either to a solo
170 number, or to the first number of a range. */
171 m_last_retval = get_number_trailer (&m_cur_tok, '-');
172 /* If get_number_trailer has found a -, it might be the start
173 of a command option. So, do not parse a range if the - is
174 followed by an alpha. */
175 if (*m_cur_tok == '-' && !isalpha (*(m_cur_tok + 1)))
179 /* This is the start of a range (<number1> - <number2>).
180 Skip the '-', parse and remember the second number,
181 and also remember the end of the final token. */
184 m_end_ptr = skip_spaces (m_cur_tok + 1);
185 m_end_value = ::get_number (temp);
186 if (m_end_value < m_last_retval)
188 error (_("inverted range"));
190 else if (m_end_value == m_last_retval)
192 /* Degenerate range (number1 == number2). Advance the
193 token pointer so that the range will be treated as a
195 m_cur_tok = m_end_ptr;
203 if (isdigit (*(m_cur_tok + 1)))
204 error (_("negative value"));
205 if (*(m_cur_tok + 1) == '$')
207 /* Convenience variable. */
208 m_last_retval = ::get_number (&m_cur_tok);
209 if (m_last_retval < 0)
210 error (_("negative value"));
213 return m_last_retval;
216 /* See documentation in cli-utils.h. */
219 number_or_range_parser::setup_range (int start_value, int end_value,
222 gdb_assert (start_value > 0);
226 m_last_retval = start_value - 1;
227 m_end_value = end_value;
230 /* See documentation in cli-utils.h. */
233 number_or_range_parser::finished () const
235 /* Parsing is finished when at end of string or null string,
236 or we are not in a range and not in front of an integer, negative
237 integer, convenience var or negative convenience var. */
238 return (m_cur_tok == NULL || *m_cur_tok == '\0'
240 && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
241 && !(*m_cur_tok == '-'
242 && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
245 /* Accept a number and a string-form list of numbers such as is
246 accepted by get_number_or_range. Return TRUE if the number is
249 By definition, an empty list includes all numbers. This is to
250 be interpreted as typing a command such as "delete break" with
254 number_is_in_list (const char *list, int number)
256 if (list == NULL || *list == '\0')
259 number_or_range_parser parser (list);
261 if (parser.finished ())
262 error (_("Arguments must be numbers or '$' variables."));
263 while (!parser.finished ())
265 int gotnum = parser.get_number ();
268 error (_("Arguments must be numbers or '$' variables."));
269 if (gotnum == number)
275 /* See documentation in cli-utils.h. */
278 remove_trailing_whitespace (const char *start, const char *s)
280 while (s > start && isspace (*(s - 1)))
286 /* See documentation in cli-utils.h. */
289 extract_arg (const char **arg)
294 return std::string ();
296 /* Find the start of the argument. */
297 *arg = skip_spaces (*arg);
299 return std::string ();
302 /* Find the end of the argument. */
303 *arg = skip_to_space (*arg + 1);
306 return std::string ();
308 return std::string (result, *arg - result);
311 /* See documentation in cli-utils.h. */
314 extract_arg (char **arg)
316 const char *arg_const = *arg;
319 result = extract_arg (&arg_const);
320 *arg += arg_const - *arg;
324 /* See documentation in cli-utils.h. */
327 check_for_argument (const char **str, const char *arg, int arg_len)
329 if (strncmp (*str, arg, arg_len) == 0
330 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
338 /* See documentation in cli-utils.h. */
341 parse_flags (const char **str, const char *flags)
343 const char *p = skip_spaces (*str);
347 && (p[2] == '\0' || isspace (p[2])))
349 const char pf = p[1];
350 const char *f = flags;
356 *str = skip_spaces (p + 2);
357 return f - flags + 1;
366 /* See documentation in cli-utils.h. */
369 parse_flags_qcs (const char *which_command, const char **str,
372 switch (parse_flags (str, "qcs"))
383 flags->silent = true;
386 gdb_assert_not_reached ("int qcs flag out of bound");
389 if (flags->cont && flags->silent)
390 error (_("%s: -c and -s are mutually exclusive"), which_command);