GDB (xrefs)
Loading...
Searching...
No Matches
cli-utils.c
Go to the documentation of this file.
1/* CLI utilities.
2
3 Copyright (C) 2011-2023 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
28ULONGEST
29get_ulongest (const char **pp, int trailer)
30{
31 LONGEST retval = 0; /* default */
32 const char *p = *pp;
33
34 if (*p == '$')
35 {
36 value *val = value_from_history_ref (p, &p);
37
38 if (val != NULL) /* Value history reference */
39 {
40 if (val->type ()->code () == TYPE_CODE_INT)
41 retval = value_as_long (val);
42 else
43 error (_("History value must have integer type."));
44 }
45 else /* Convenience variable */
46 {
47 /* Internal variable. Make a copy of the name, so we can
48 null-terminate it to pass to lookup_internalvar(). */
49 const char *start = ++p;
50 while (isalnum (*p) || *p == '_')
51 p++;
52 std::string varname (start, p - start);
53 if (!get_internalvar_integer (lookup_internalvar (varname.c_str ()),
54 &retval))
55 error (_("Convenience variable $%s does not have integer value."),
56 varname.c_str ());
57 }
58 }
59 else
60 {
61 const char *end = p;
62 retval = strtoulst (p, &end, 0);
63 if (p == end)
64 {
65 /* There is no number here. (e.g. "cond a == b"). */
66 error (_("Expected integer at: %s"), p);
67 }
68 p = end;
69 }
70
71 if (!(isspace (*p) || *p == '\0' || *p == trailer))
72 error (_("Trailing junk at: %s"), p);
73 p = skip_spaces (p);
74 *pp = p;
75 return retval;
76}
77
78/* See documentation in cli-utils.h. */
79
80int
81get_number_trailer (const char **pp, int trailer)
82{
83 int retval = 0; /* default */
84 const char *p = *pp;
85 bool negative = false;
86
87 if (*p == '-')
88 {
89 ++p;
90 negative = true;
91 }
92
93 if (*p == '$')
94 {
95 struct value *val = value_from_history_ref (p, &p);
96
97 if (val) /* Value history reference */
98 {
99 if (val->type ()->code () == TYPE_CODE_INT)
100 retval = value_as_long (val);
101 else
102 {
103 gdb_printf (_("History value must have integer type.\n"));
104 retval = 0;
105 }
106 }
107 else /* Convenience variable */
108 {
109 /* Internal variable. Make a copy of the name, so we can
110 null-terminate it to pass to lookup_internalvar(). */
111 char *varname;
112 const char *start = ++p;
113 LONGEST longest_val;
114
115 while (isalnum (*p) || *p == '_')
116 p++;
117 varname = (char *) alloca (p - start + 1);
118 strncpy (varname, start, p - start);
119 varname[p - start] = '\0';
121 &longest_val))
122 retval = (int) longest_val;
123 else
124 {
125 gdb_printf (_("Convenience variable must "
126 "have integer value.\n"));
127 retval = 0;
128 }
129 }
130 }
131 else
132 {
133 const char *p1 = p;
134 while (*p >= '0' && *p <= '9')
135 ++p;
136 if (p == p1)
137 /* There is no number here. (e.g. "cond a == b"). */
138 {
139 /* Skip non-numeric token. */
140 while (*p && !isspace((int) *p))
141 ++p;
142 /* Return zero, which caller must interpret as error. */
143 retval = 0;
144 }
145 else
146 retval = atoi (p1);
147 }
148 if (!(isspace (*p) || *p == '\0' || *p == trailer))
149 {
150 /* Trailing junk: return 0 and let caller print error msg. */
151 while (!(isspace (*p) || *p == '\0' || *p == trailer))
152 ++p;
153 retval = 0;
154 }
155 p = skip_spaces (p);
156 *pp = p;
157 return negative ? -retval : retval;
158}
159
160/* See documentation in cli-utils.h. */
161
162int
163get_number (const char **pp)
164{
165 return get_number_trailer (pp, '\0');
166}
167
168/* See documentation in cli-utils.h. */
169
170int
171get_number (char **pp)
172{
173 int result;
174 const char *p = *pp;
175
176 result = get_number_trailer (&p, '\0');
177 *pp = (char *) p;
178 return result;
179}
180
181/* See documentation in cli-utils.h. */
182
183void
184report_unrecognized_option_error (const char *command, const char *args)
185{
186 std::string option = extract_arg (&args);
187
188 error (_("Unrecognized option '%s' to %s command. "
189 "Try \"help %s\"."), option.c_str (),
190 command, command);
191}
192
193/* See documentation in cli-utils.h. */
194
195const char *
197 const char *entity_kind,
198 bool document_n_flag)
199{
200 return xstrprintf (_("\
201%sIf NAMEREGEXP is provided, only prints the %s whose name\n\
202matches NAMEREGEXP.\n\
203If -t TYPEREGEXP is provided, only prints the %s whose type\n\
204matches TYPEREGEXP. Note that the matching is done with the type\n\
205printed by the 'whatis' command.\n\
206By default, the command might produce headers and/or messages indicating\n\
207why no %s can be printed.\n\
208The flag -q disables the production of these headers and messages.%s"),
209 prefix, entity_kind, entity_kind, entity_kind,
210 (document_n_flag ? _("\n\
211By default, the command will include non-debug symbols in the output;\n\
212these can be excluded using the -n flag.") : "")).release ();
213}
214
215/* See documentation in cli-utils.h. */
216
218{
219 init (string);
220}
221
222/* See documentation in cli-utils.h. */
223
224void
226{
227 m_cur_tok = string;
228 m_last_retval = 0;
229 m_end_value = 0;
230 m_end_ptr = NULL;
231 m_in_range = false;
232}
233
234/* See documentation in cli-utils.h. */
235
236int
238{
239 if (m_in_range)
240 {
241 /* All number-parsing has already been done. Return the next
242 integer value (one greater than the saved previous value).
243 Do not advance the token pointer until the end of range is
244 reached. */
245
246 if (++m_last_retval == m_end_value)
247 {
248 /* End of range reached; advance token pointer. */
250 m_in_range = false;
251 }
252 }
253 else if (*m_cur_tok != '-')
254 {
255 /* Default case: state->m_cur_tok is pointing either to a solo
256 number, or to the first number of a range. */
258 /* If get_number_trailer has found a '-' preceded by a space, it
259 might be the start of a command option. So, do not parse a
260 range if the '-' is followed by an alpha or another '-'. We
261 might also be completing something like
262 "frame apply level 0 -" and we prefer treating that "-" as an
263 option rather than an incomplete range, so check for end of
264 string as well. */
265 if (m_cur_tok[0] == '-'
266 && !(isspace (m_cur_tok[-1])
267 && (isalpha (m_cur_tok[1])
268 || m_cur_tok[1] == '-'
269 || m_cur_tok[1] == '\0')))
270 {
271 const char **temp;
272
273 /* This is the start of a range (<number1> - <number2>).
274 Skip the '-', parse and remember the second number,
275 and also remember the end of the final token. */
276
277 temp = &m_end_ptr;
278 m_end_ptr = skip_spaces (m_cur_tok + 1);
279 m_end_value = ::get_number (temp);
281 {
282 error (_("inverted range"));
283 }
284 else if (m_end_value == m_last_retval)
285 {
286 /* Degenerate range (number1 == number2). Advance the
287 token pointer so that the range will be treated as a
288 single number. */
290 }
291 else
292 m_in_range = true;
293 }
294 }
295 else
296 {
297 if (isdigit (*(m_cur_tok + 1)))
298 error (_("negative value"));
299 if (*(m_cur_tok + 1) == '$')
300 {
301 /* Convenience variable. */
303 if (m_last_retval < 0)
304 error (_("negative value"));
305 }
306 }
307 return m_last_retval;
308}
309
310/* See documentation in cli-utils.h. */
311
312void
313number_or_range_parser::setup_range (int start_value, int end_value,
314 const char *end_ptr)
315{
316 gdb_assert (start_value > 0);
317
318 m_in_range = true;
319 m_end_ptr = end_ptr;
320 m_last_retval = start_value - 1;
322}
323
324/* See documentation in cli-utils.h. */
325
326bool
328{
329 /* Parsing is finished when at end of string or null string,
330 or we are not in a range and not in front of an integer, negative
331 integer, convenience var or negative convenience var. */
332 return (m_cur_tok == NULL || *m_cur_tok == '\0'
333 || (!m_in_range
334 && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
335 && !(*m_cur_tok == '-'
336 && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
337}
338
339/* Accept a number and a string-form list of numbers such as is
340 accepted by get_number_or_range. Return TRUE if the number is
341 in the list.
342
343 By definition, an empty list includes all numbers. This is to
344 be interpreted as typing a command such as "delete break" with
345 no arguments. */
346
347int
348number_is_in_list (const char *list, int number)
349{
350 if (list == NULL || *list == '\0')
351 return 1;
352
353 number_or_range_parser parser (list);
354
355 if (parser.finished ())
356 error (_("Arguments must be numbers or '$' variables."));
357 while (!parser.finished ())
358 {
359 int gotnum = parser.get_number ();
360
361 if (gotnum == 0)
362 error (_("Arguments must be numbers or '$' variables."));
363 if (gotnum == number)
364 return 1;
365 }
366 return 0;
367}
368
369/* See documentation in cli-utils.h. */
370
371const char *
372remove_trailing_whitespace (const char *start, const char *s)
373{
374 while (s > start && isspace (*(s - 1)))
375 --s;
376
377 return s;
378}
379
380/* See documentation in cli-utils.h. */
381
382std::string
383extract_arg (const char **arg)
384{
385 const char *result;
386
387 if (!*arg)
388 return std::string ();
389
390 /* Find the start of the argument. */
391 *arg = skip_spaces (*arg);
392 if (!**arg)
393 return std::string ();
394 result = *arg;
395
396 /* Find the end of the argument. */
397 *arg = skip_to_space (*arg + 1);
398
399 if (result == *arg)
400 return std::string ();
401
402 return std::string (result, *arg - result);
403}
404
405/* See documentation in cli-utils.h. */
406
407std::string
408extract_arg (char **arg)
409{
410 const char *arg_const = *arg;
411 std::string result;
412
413 result = extract_arg (&arg_const);
414 *arg += arg_const - *arg;
415 return result;
416}
417
418/* See documentation in cli-utils.h. */
419
420int
421check_for_argument (const char **str, const char *arg, int arg_len)
422{
423 if (strncmp (*str, arg, arg_len) == 0
424 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
425 {
426 *str += arg_len;
427 *str = skip_spaces (*str);
428 return 1;
429 }
430 return 0;
431}
432
433/* See documentation in cli-utils.h. */
434
435void
436validate_flags_qcs (const char *which_command, qcs_flags *flags)
437{
438 if (flags->cont && flags->silent)
439 error (_("%s: -c and -s are mutually exclusive"), which_command);
440}
441
int end_value() const
Definition cli-utils.h:114
bool finished() const
Definition cli-utils.c:327
const char * m_cur_tok
Definition cli-utils.h:132
void init(const char *string)
Definition cli-utils.c:225
void setup_range(int start_value, int end_value, const char *end_ptr)
Definition cli-utils.c:313
const char * m_end_ptr
Definition cli-utils.h:142
const char * info_print_args_help(const char *prefix, const char *entity_kind, bool document_n_flag)
Definition cli-utils.c:196
void report_unrecognized_option_error(const char *command, const char *args)
Definition cli-utils.c:184
int get_number(const char **pp)
Definition cli-utils.c:163
int number_is_in_list(const char *list, int number)
Definition cli-utils.c:348
ULONGEST get_ulongest(const char **pp, int trailer)
Definition cli-utils.c:29
void validate_flags_qcs(const char *which_command, qcs_flags *flags)
Definition cli-utils.c:436
int check_for_argument(const char **str, const char *arg, int arg_len)
Definition cli-utils.c:421
const char * remove_trailing_whitespace(const char *start, const char *s)
Definition cli-utils.c:372
std::string extract_arg(const char **arg)
Definition cli-utils.c:383
int get_number_trailer(const char **pp, int trailer)
Definition cli-utils.c:81
int get_number_trailer(const char **pp, int trailer)
Definition cli-utils.c:81
mach_port_t kern_return_t mach_port_t mach_msg_type_name_t msgportsPoly mach_port_t kern_return_t pid_t pid mach_port_t kern_return_t mach_port_t task mach_port_t kern_return_t int flags
Definition gnu-nat.c:1861
#define prefix(a, b, R, do)
Definition ppc64-tdep.c:52
type_code code() const
Definition gdbtypes.h:956
Definition value.h:130
struct type * type() const
Definition value.h:180
void gdb_printf(struct ui_file *stream, const char *format,...)
Definition utils.c:1886
struct value * value_from_history_ref(const char *h, const char **endp)
Definition value.c:3595
struct internalvar * lookup_internalvar(const char *name)
Definition value.c:2001
LONGEST value_as_long(struct value *val)
Definition value.c:2554
int get_internalvar_integer(struct internalvar *var, LONGEST *result)
Definition value.c:2103