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
130 number_or_range_parser::number_or_range_parser (const char *string)
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
151 number_or_range_parser::get_number ()
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. */
163 m_cur_tok = m_end_ptr;
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. */
171 m_last_retval = get_number_trailer (&m_cur_tok, '-');
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;
181 m_end_ptr = skip_spaces (m_cur_tok + 1);
182 m_end_value = ::get_number (temp);
183 if (m_end_value < m_last_retval)
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. */
192 m_cur_tok = m_end_ptr;
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;
215 m_end_value = end_value;
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
258 std::string
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
283 std::string
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 }
string
const char * string
Definition: signals.c:50
number_or_range_parser::m_in_range
bool m_in_range
Definition: cli-utils.h:124
value_as_long
LONGEST value_as_long(struct value *val)
Definition: value.c:2749
number_is_in_list
int number_is_in_list(const char *list, int number)
Definition: cli-utils.c:227
number_or_range_parser::m_cur_tok
const char * m_cur_tok
Definition: cli-utils.h:111
get_internalvar_integer
int get_internalvar_integer(struct internalvar *var, LONGEST *result)
Definition: value.c:2313
extract_arg
std::string extract_arg(const char **arg)
Definition: cli-utils.c:259
TYPE_CODE_INT
Definition: gdbtypes.h:111
number_or_range_parser::m_end_ptr
const char * m_end_ptr
Definition: cli-utils.h:121
lookup_internalvar
struct internalvar * lookup_internalvar(const char *name)
Definition: value.c:2212
skip_spaces
char * skip_spaces(char *chp)
Definition: common-utils.c:337
_
#define _(String)
Definition: gdb_locale.h:35
number_or_range_parser::m_end_value
int m_end_value
Definition: cli-utils.h:117
defs.h
printf_filtered
void printf_filtered(const char *format,...)
Definition: utils.c:2045
remove_trailing_whitespace
const char * remove_trailing_whitespace(const char *start, const char *s)
Definition: cli-utils.c:248
number_or_range_parser::m_finished
bool m_finished
Definition: cli-utils.h:107
number_or_range_parser::finished
bool finished() const
Definition: cli-utils.h:78
cli-utils.h
get_number_trailer
int get_number_trailer(const char **pp, int trailer)
Definition: cli-utils.c:29
number_or_range_parser::setup_range
void setup_range(int start_value, int end_value, const char *end_ptr)
Definition: cli-utils.c:207
skip_to_space
const char * skip_to_space(const char *chp)
Definition: common-utils.c:361
number_or_range_parser::m_last_retval
int m_last_retval
Definition: cli-utils.h:114
gdb_assert
#define gdb_assert(expr)
Definition: gdb_assert.h:32
value
Definition: value.c:169
number_or_range_parser::init
void init(const char *string)
Definition: cli-utils.c:138
number_or_range_parser::end_value
int end_value() const
Definition: cli-utils.h:91
TYPE_CODE
#define TYPE_CODE(thistype)
Definition: gdbtypes.h:1238
value.h
number_or_range_parser
Definition: cli-utils.h:48
number_or_range_parser::number_or_range_parser
number_or_range_parser()
Definition: cli-utils.h:53
value_type
struct type * value_type(const struct value *value)
Definition: value.c:1095
number_or_range_parser::get_number
int get_number()
Definition: cli-utils.c:151
error
void error(const char *fmt,...)
Definition: errors.c:38
value_from_history_ref
struct value * value_from_history_ref(const char *h, const char **endp)
Definition: value.c:3637
get_number
int get_number(const char **pp)
Definition: cli-utils.c:110
check_for_argument
int check_for_argument(const char **str, const char *arg, int arg_len)
Definition: cli-utils.c:297
LONGEST
long long LONGEST
Definition: common-types.h:52