3 Copyright (c) 2011-2012 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"
22 #include "gdb_string.h"
24 #include "gdb_assert.h"
28 /* *PP is a string denoting a number. Get the number of the. Advance
29 *PP after the string and any trailing whitespace.
31 Currently the string can either be a number, or "$" followed by the
32 name of a convenience variable, or ("$" or "$$") followed by digits.
34 TRAILER is a character which can be found after the number; most
35 commonly this is `-'. If you don't want a trailer, use \0. */
38 get_number_trailer (char **pp, int trailer)
40 int retval = 0; /* default */
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."));
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(). */
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), &val))
74 printf_filtered (_("Convenience variable must "
75 "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))
110 /* See documentation in cli-utils.h. */
113 get_number (char **pp)
115 return get_number_trailer (pp, '\0');
118 /* See documentation in cli-utils.h. */
121 init_number_or_range (struct get_number_or_range_state *state,
124 memset (state, 0, sizeof (*state));
125 state->string = string;
128 /* See documentation in cli-utils.h. */
131 get_number_or_range (struct get_number_or_range_state *state)
133 if (*state->string != '-')
135 /* Default case: state->string is pointing either to a solo
136 number, or to the first number of a range. */
137 state->last_retval = get_number_trailer (&state->string, '-');
138 if (*state->string == '-')
142 /* This is the start of a range (<number1> - <number2>).
143 Skip the '-', parse and remember the second number,
144 and also remember the end of the final token. */
146 temp = &state->end_ptr;
147 state->end_ptr = skip_spaces (state->string + 1);
148 state->end_value = get_number (temp);
149 if (state->end_value < state->last_retval)
151 error (_("inverted range"));
153 else if (state->end_value == state->last_retval)
155 /* Degenerate range (number1 == number2). Advance the
156 token pointer so that the range will be treated as a
158 state->string = state->end_ptr;
164 else if (! state->in_range)
165 error (_("negative value"));
168 /* state->string points to the '-' that betokens a range. All
169 number-parsing has already been done. Return the next
170 integer value (one greater than the saved previous value).
171 Do not advance the token pointer until the end of range
174 if (++state->last_retval == state->end_value)
176 /* End of range reached; advance token pointer. */
177 state->string = state->end_ptr;
181 state->finished = *state->string == '\0';
182 return state->last_retval;
185 /* Accept a number and a string-form list of numbers such as is
186 accepted by get_number_or_range. Return TRUE if the number is
189 By definition, an empty list includes all numbers. This is to
190 be interpreted as typing a command such as "delete break" with
194 number_is_in_list (char *list, int number)
196 struct get_number_or_range_state state;
198 if (list == NULL || *list == '\0')
201 init_number_or_range (&state, list);
202 while (!state.finished)
204 int gotnum = get_number_or_range (&state);
207 error (_("Args must be numbers or '$' variables."));
208 if (gotnum == number)
214 /* See documentation in cli-utils.h. */
217 skip_spaces (char *chp)
221 while (*chp && isspace (*chp))
226 /* A const-correct version of the above. */
229 skip_spaces_const (const char *chp)
233 while (*chp && isspace (*chp))
238 /* See documentation in cli-utils.h. */
241 skip_to_space (char *chp)
245 while (*chp && !isspace (*chp))
250 /* See documentation in cli-utils.h. */
253 remove_trailing_whitespace (const char *start, char *s)
255 while (s > start && isspace (*(s - 1)))
261 /* See documentation in cli-utils.h. */
264 extract_arg (char **arg)
271 /* Find the start of the argument. */
272 *arg = skip_spaces (*arg);
277 /* Find the end of the argument. */
278 *arg = skip_to_space (*arg + 1);
283 copy = xmalloc (*arg - result + 1);
284 memcpy (copy, result, *arg - result);
285 copy[*arg - result] = '\0';
290 /* See documentation in cli-utils.h. */
293 check_for_argument (char **str, char *arg, int arg_len)
295 if (strncmp (*str, arg, arg_len) == 0
296 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))