GDB (xrefs)
cli-utils.c
Go to the documentation of this file.
1 /* CLI utilities.
2 
3  Copyright (C) 2011-2015 Free Software Foundation, Inc.
4 
5  This file is part of GDB.
6 
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.
11 
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.
16 
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/>. */
19 
20 #include "defs.h"
21 #include "cli/cli-utils.h"
22 #include "value.h"
23 
24 #include <ctype.h>
25 
26 /* *PP is a string denoting a number. Get the number of the. Advance
27  *PP after the string and any trailing whitespace.
28 
29  Currently the string can either be a number, or "$" followed by the
30  name of a convenience variable, or ("$" or "$$") followed by digits.
31 
32  TRAILER is a character which can be found after the number; most
33  commonly this is `-'. If you don't want a trailer, use \0. */
34 
35 static int
36 get_number_trailer (const char **pp, int trailer)
37 {
38  int retval = 0; /* default */
39  const char *p = *pp;
40 
41  if (*p == '$')
42  {
43  struct value *val = value_from_history_ref (p, &p);
44 
45  if (val) /* Value history reference */
46  {
47  if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
48  retval = value_as_long (val);
49  else
50  {
51  printf_filtered (_("History value must have integer type.\n"));
52  retval = 0;
53  }
54  }
55  else /* Convenience variable */
56  {
57  /* Internal variable. Make a copy of the name, so we can
58  null-terminate it to pass to lookup_internalvar(). */
59  char *varname;
60  const char *start = ++p;
61  LONGEST val;
62 
63  while (isalnum (*p) || *p == '_')
64  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))
69  retval = (int) val;
70  else
71  {
72  printf_filtered (_("Convenience variable must "
73  "have integer value.\n"));
74  retval = 0;
75  }
76  }
77  }
78  else
79  {
80  if (*p == '-')
81  ++p;
82  while (*p >= '0' && *p <= '9')
83  ++p;
84  if (p == *pp)
85  /* There is no number here. (e.g. "cond a == b"). */
86  {
87  /* Skip non-numeric token. */
88  while (*p && !isspace((int) *p))
89  ++p;
90  /* Return zero, which caller must interpret as error. */
91  retval = 0;
92  }
93  else
94  retval = atoi (*pp);
95  }
96  if (!(isspace (*p) || *p == '\0' || *p == trailer))
97  {
98  /* Trailing junk: return 0 and let caller print error msg. */
99  while (!(isspace (*p) || *p == '\0' || *p == trailer))
100  ++p;
101  retval = 0;
102  }
103  p = skip_spaces_const (p);
104  *pp = p;
105  return retval;
106 }
107 
108 /* See documentation in cli-utils.h. */
109 
110 int
111 get_number_const (const char **pp)
112 {
113  return get_number_trailer (pp, '\0');
114 }
115 
116 /* See documentation in cli-utils.h. */
117 
118 int
119 get_number (char **pp)
120 {
121  int result;
122  const char *p = *pp;
123 
124  result = get_number_trailer (&p, '\0');
125  *pp = (char *) p;
126  return result;
127 }
128 
129 /* See documentation in cli-utils.h. */
130 
131 void
133  const char *string)
134 {
135  memset (state, 0, sizeof (*state));
136  state->string = string;
137 }
138 
139 /* See documentation in cli-utils.h. */
140 
141 int
143 {
144  if (*state->string != '-')
145  {
146  /* Default case: state->string is pointing either to a solo
147  number, or to the first number of a range. */
148  state->last_retval = get_number_trailer (&state->string, '-');
149  if (*state->string == '-')
150  {
151  const char **temp;
152 
153  /* This is the start of a range (<number1> - <number2>).
154  Skip the '-', parse and remember the second number,
155  and also remember the end of the final token. */
156 
157  temp = &state->end_ptr;
158  state->end_ptr = skip_spaces_const (state->string + 1);
159  state->end_value = get_number_const (temp);
160  if (state->end_value < state->last_retval)
161  {
162  error (_("inverted range"));
163  }
164  else if (state->end_value == state->last_retval)
165  {
166  /* Degenerate range (number1 == number2). Advance the
167  token pointer so that the range will be treated as a
168  single number. */
169  state->string = state->end_ptr;
170  }
171  else
172  state->in_range = 1;
173  }
174  }
175  else if (! state->in_range)
176  error (_("negative value"));
177  else
178  {
179  /* state->string points to the '-' that betokens a range. All
180  number-parsing has already been done. Return the next
181  integer value (one greater than the saved previous value).
182  Do not advance the token pointer until the end of range
183  is reached. */
184 
185  if (++state->last_retval == state->end_value)
186  {
187  /* End of range reached; advance token pointer. */
188  state->string = state->end_ptr;
189  state->in_range = 0;
190  }
191  }
192  state->finished = *state->string == '\0';
193  return state->last_retval;
194 }
195 
196 /* Accept a number and a string-form list of numbers such as is
197  accepted by get_number_or_range. Return TRUE if the number is
198  in the list.
199 
200  By definition, an empty list includes all numbers. This is to
201  be interpreted as typing a command such as "delete break" with
202  no arguments. */
203 
204 int
205 number_is_in_list (const char *list, int number)
206 {
207  struct get_number_or_range_state state;
208 
209  if (list == NULL || *list == '\0')
210  return 1;
211 
212  init_number_or_range (&state, list);
213  while (!state.finished)
214  {
215  int gotnum = get_number_or_range (&state);
216 
217  if (gotnum == 0)
218  error (_("Args must be numbers or '$' variables."));
219  if (gotnum == number)
220  return 1;
221  }
222  return 0;
223 }
224 
225 /* See documentation in cli-utils.h. */
226 
227 char *
228 remove_trailing_whitespace (const char *start, char *s)
229 {
230  while (s > start && isspace (*(s - 1)))
231  --s;
232 
233  return s;
234 }
235 
236 /* See documentation in cli-utils.h. */
237 
238 char *
239 extract_arg_const (const char **arg)
240 {
241  const char *result;
242 
243  if (!*arg)
244  return NULL;
245 
246  /* Find the start of the argument. */
247  *arg = skip_spaces_const (*arg);
248  if (!**arg)
249  return NULL;
250  result = *arg;
251 
252  /* Find the end of the argument. */
253  *arg = skip_to_space_const (*arg + 1);
254 
255  if (result == *arg)
256  return NULL;
257 
258  return savestring (result, *arg - result);
259 }
260 
261 /* See documentation in cli-utils.h. */
262 
263 char *
264 extract_arg (char **arg)
265 {
266  const char *arg_const = *arg;
267  char *result;
268 
269  result = extract_arg_const (&arg_const);
270  *arg += arg_const - *arg;
271  return result;
272 }
273 
274 /* See documentation in cli-utils.h. */
275 
276 int
277 check_for_argument (char **str, char *arg, int arg_len)
278 {
279  if (strncmp (*str, arg, arg_len) == 0
280  && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
281  {
282  *str += arg_len;
283  return 1;
284  }
285  return 0;
286 }
const char * string
Definition: signals.c:50
LONGEST value_as_long(struct value *val)
Definition: value.c:2654
int number_is_in_list(const char *list, int number)
Definition: cli-utils.c:205
int get_internalvar_integer(struct internalvar *var, LONGEST *result)
Definition: value.c:2232
const char * skip_to_space_const(const char *chp)
Definition: common-utils.c:283
static int get_number_trailer(const char **pp, int trailer)
Definition: cli-utils.c:36
struct internalvar * lookup_internalvar(const char *name)
Definition: value.c:2131
#define _(String)
Definition: gdb_locale.h:40
int get_number(char **pp)
Definition: cli-utils.c:119
void printf_filtered(const char *format,...)
Definition: utils.c:2388
int check_for_argument(char **str, char *arg, int arg_len)
Definition: cli-utils.c:277
const char * skip_spaces_const(const char *chp)
Definition: common-utils.c:271
char * extract_arg(char **arg)
Definition: cli-utils.c:264
char * remove_trailing_whitespace(const char *start, char *s)
Definition: cli-utils.c:228
Definition: value.c:172
const char const char int
Definition: command.h:229
#define TYPE_CODE(thistype)
Definition: gdbtypes.h:1240
int get_number_const(const char **pp)
Definition: cli-utils.c:111
char * extract_arg_const(const char **arg)
Definition: cli-utils.c:239
char * savestring(const char *ptr, size_t len)
Definition: common-utils.c:148
struct type * value_type(const struct value *value)
Definition: value.c:1021
int get_number_or_range(struct get_number_or_range_state *state)
Definition: cli-utils.c:142
const char * end_ptr
Definition: cli-utils.h:57
void error(const char *fmt,...)
Definition: errors.c:38
struct value * value_from_history_ref(const char *h, const char **endp)
Definition: value.c:3593
long long LONGEST
Definition: common-types.h:52
void init_number_or_range(struct get_number_or_range_state *state, const char *string)
Definition: cli-utils.c:132