GDB (xrefs)
cli-utils.c
Go to the documentation of this file.
1 /* CLI utilities.
2 
3  Copyright (C) 2011-2018 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 /* See documentation in cli-utils.h. */
27 
28 int
29 get_number_trailer (const char **pp, int trailer)
30 {
31  int retval = 0; /* default */
32  const char *p = *pp;
33  bool negative = false;
34 
35  if (*p == '-')
36  {
37  ++p;
38  negative = true;
39  }
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  const char *p1 = p;
81  while (*p >= '0' && *p <= '9')
82  ++p;
83  if (p == p1)
84  /* There is no number here. (e.g. "cond a == b"). */
85  {
86  /* Skip non-numeric token. */
87  while (*p && !isspace((int) *p))
88  ++p;
89  /* Return zero, which caller must interpret as error. */
90  retval = 0;
91  }
92  else
93  retval = atoi (p1);
94  }
95  if (!(isspace (*p) || *p == '\0' || *p == trailer))
96  {
97  /* Trailing junk: return 0 and let caller print error msg. */
98  while (!(isspace (*p) || *p == '\0' || *p == trailer))
99  ++p;
100  retval = 0;
101  }
102  p = skip_spaces (p);
103  *pp = p;
104  return negative ? -retval : retval;
105 }
106 
107 /* See documentation in cli-utils.h. */
108 
109 int
110 get_number (const char **pp)
111 {
112  return get_number_trailer (pp, '\0');
113 }
114 
115 /* See documentation in cli-utils.h. */
116 
117 int
118 get_number (char **pp)
119 {
120  int result;
121  const char *p = *pp;
122 
123  result = get_number_trailer (&p, '\0');
124  *pp = (char *) p;
125  return result;
126 }
127 
128 /* See documentation in cli-utils.h. */
129 
131 {
132  init (string);
133 }
134 
135 /* See documentation in cli-utils.h. */
136 
137 void
138 number_or_range_parser::init (const char *string)
139 {
140  m_finished = false;
141  m_cur_tok = string;
142  m_last_retval = 0;
143  m_end_value = 0;
144  m_end_ptr = NULL;
145  m_in_range = false;
146 }
147 
148 /* See documentation in cli-utils.h. */
149 
150 int
152 {
153  if (m_in_range)
154  {
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
158  reached. */
159 
160  if (++m_last_retval == m_end_value)
161  {
162  /* End of range reached; advance token pointer. */
164  m_in_range = false;
165  }
166  }
167  else if (*m_cur_tok != '-')
168  {
169  /* Default case: state->m_cur_tok is pointing either to a solo
170  number, or to the first number of a range. */
172  if (*m_cur_tok == '-')
173  {
174  const char **temp;
175 
176  /* This is the start of a range (<number1> - <number2>).
177  Skip the '-', parse and remember the second number,
178  and also remember the end of the final token. */
179 
180  temp = &m_end_ptr;
182  m_end_value = ::get_number (temp);
184  {
185  error (_("inverted range"));
186  }
187  else if (m_end_value == m_last_retval)
188  {
189  /* Degenerate range (number1 == number2). Advance the
190  token pointer so that the range will be treated as a
191  single number. */
193  }
194  else
195  m_in_range = true;
196  }
197  }
198  else
199  error (_("negative value"));
200  m_finished = *m_cur_tok == '\0';
201  return m_last_retval;
202 }
203 
204 /* See documentation in cli-utils.h. */
205 
206 void
207 number_or_range_parser::setup_range (int start_value, int end_value,
208  const char *end_ptr)
209 {
210  gdb_assert (start_value > 0);
211 
212  m_in_range = true;
213  m_end_ptr = end_ptr;
214  m_last_retval = start_value - 1;
216 }
217 
218 /* Accept a number and a string-form list of numbers such as is
219  accepted by get_number_or_range. Return TRUE if the number is
220  in the list.
221 
222  By definition, an empty list includes all numbers. This is to
223  be interpreted as typing a command such as "delete break" with
224  no arguments. */
225 
226 int
227 number_is_in_list (const char *list, int number)
228 {
229  if (list == NULL || *list == '\0')
230  return 1;
231 
232  number_or_range_parser parser (list);
233  while (!parser.finished ())
234  {
235  int gotnum = parser.get_number ();
236 
237  if (gotnum == 0)
238  error (_("Args must be numbers or '$' variables."));
239  if (gotnum == number)
240  return 1;
241  }
242  return 0;
243 }
244 
245 /* See documentation in cli-utils.h. */
246 
247 const char *
248 remove_trailing_whitespace (const char *start, const char *s)
249 {
250  while (s > start && isspace (*(s - 1)))
251  --s;
252 
253  return s;
254 }
255 
256 /* See documentation in cli-utils.h. */
257 
259 extract_arg (const char **arg)
260 {
261  const char *result;
262 
263  if (!*arg)
264  return std::string ();
265 
266  /* Find the start of the argument. */
267  *arg = skip_spaces (*arg);
268  if (!**arg)
269  return std::string ();
270  result = *arg;
271 
272  /* Find the end of the argument. */
273  *arg = skip_to_space (*arg + 1);
274 
275  if (result == *arg)
276  return std::string ();
277 
278  return std::string (result, *arg - result);
279 }
280 
281 /* See documentation in cli-utils.h. */
282 
284 extract_arg (char **arg)
285 {
286  const char *arg_const = *arg;
287  std::string result;
288 
289  result = extract_arg (&arg_const);
290  *arg += arg_const - *arg;
291  return result;
292 }
293 
294 /* See documentation in cli-utils.h. */
295 
296 int
297 check_for_argument (const char **str, const char *arg, int arg_len)
298 {
299  if (strncmp (*str, arg, arg_len) == 0
300  && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
301  {
302  *str += arg_len;
303  return 1;
304  }
305  return 0;
306 }
const char * string
Definition: signals.c:50
LONGEST value_as_long(struct value *val)
Definition: value.c:2749
int number_is_in_list(const char *list, int number)
Definition: cli-utils.c:227
const char * m_cur_tok
Definition: cli-utils.h:111
int get_internalvar_integer(struct internalvar *var, LONGEST *result)
Definition: value.c:2313
std::string extract_arg(const char **arg)
Definition: cli-utils.c:259
const char * m_end_ptr
Definition: cli-utils.h:121
struct internalvar * lookup_internalvar(const char *name)
Definition: value.c:2212
char * skip_spaces(char *chp)
Definition: common-utils.c:337
#define _(String)
Definition: gdb_locale.h:35
void printf_filtered(const char *format,...)
Definition: utils.c:2045
const char * remove_trailing_whitespace(const char *start, const char *s)
Definition: cli-utils.c:248
bool finished() const
Definition: cli-utils.h:78
int get_number_trailer(const char **pp, int trailer)
Definition: cli-utils.c:29
void setup_range(int start_value, int end_value, const char *end_ptr)
Definition: cli-utils.c:207
const char * skip_to_space(const char *chp)
Definition: common-utils.c:361
#define gdb_assert(expr)
Definition: gdb_assert.h:32
Definition: value.c:169
void init(const char *string)
Definition: cli-utils.c:138
int end_value() const
Definition: cli-utils.h:91
#define TYPE_CODE(thistype)
Definition: gdbtypes.h:1238
struct type * value_type(const struct value *value)
Definition: value.c:1095
void error(const char *fmt,...)
Definition: errors.c:38
struct value * value_from_history_ref(const char *h, const char **endp)
Definition: value.c:3637
int get_number(const char **pp)
Definition: cli-utils.c:110
int check_for_argument(const char **str, const char *arg, int arg_len)
Definition: cli-utils.c:297
long long LONGEST
Definition: common-types.h:52