gdb: Add new -n flag to some info commands
[deliverable/binutils-gdb.git] / gdb / cli / cli-utils.c
CommitLineData
e9cafbcc
TT
1/* CLI utilities.
2
42a4f53d 3 Copyright (C) 2011-2019 Free Software Foundation, Inc.
e9cafbcc
TT
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"
e9cafbcc
TT
22#include "value.h"
23
24#include <ctype.h>
25
5d5658a1 26/* See documentation in cli-utils.h. */
e9cafbcc 27
9d0faba9
PA
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 (TYPE_CODE (value_type (val)) == 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 {
41fc454c
PA
61 const char *end = p;
62 retval = strtoulst (p, &end, 0);
63 if (p == end)
9d0faba9
PA
64 {
65 /* There is no number here. (e.g. "cond a == b"). */
66 error (_("Expected integer at: %s"), p);
67 }
41fc454c 68 p = end;
9d0faba9
PA
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
5d5658a1 80int
e799154c 81get_number_trailer (const char **pp, int trailer)
e9cafbcc
TT
82{
83 int retval = 0; /* default */
e799154c 84 const char *p = *pp;
95e95a6d
PA
85 bool negative = false;
86
87 if (*p == '-')
88 {
89 ++p;
90 negative = true;
91 }
e9cafbcc
TT
92
93 if (*p == '$')
94 {
3bd0f5ef 95 struct value *val = value_from_history_ref (p, &p);
e9cafbcc 96
3bd0f5ef 97 if (val) /* Value history reference */
e9cafbcc 98 {
3bd0f5ef
MS
99 if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
100 retval = value_as_long (val);
101 else
102 {
2217da06 103 printf_filtered (_("History value must have integer type.\n"));
3bd0f5ef
MS
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;
e799154c 112 const char *start = ++p;
b926417a 113 LONGEST longest_val;
3bd0f5ef
MS
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';
b926417a
TT
120 if (get_internalvar_integer (lookup_internalvar (varname),
121 &longest_val))
122 retval = (int) longest_val;
3bd0f5ef
MS
123 else
124 {
125 printf_filtered (_("Convenience variable must "
126 "have integer value.\n"));
127 retval = 0;
128 }
e9cafbcc
TT
129 }
130 }
131 else
132 {
95e95a6d 133 const char *p1 = p;
e9cafbcc
TT
134 while (*p >= '0' && *p <= '9')
135 ++p;
95e95a6d 136 if (p == p1)
e9cafbcc
TT
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
95e95a6d 146 retval = atoi (p1);
e9cafbcc
TT
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 }
f1735a53 155 p = skip_spaces (p);
e9cafbcc 156 *pp = p;
95e95a6d 157 return negative ? -retval : retval;
e9cafbcc
TT
158}
159
160/* See documentation in cli-utils.h. */
161
162int
f1735a53 163get_number (const char **pp)
e9cafbcc
TT
164{
165 return get_number_trailer (pp, '\0');
166}
167
168/* See documentation in cli-utils.h. */
169
e799154c
TT
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
0d4cad90
PW
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 *
196info_print_args_help (const char *prefix,
4acfdd20
AB
197 const char *entity_kind,
198 bool document_n_flag)
0d4cad90
PW
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\
4acfdd20
AB
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.") : ""));
0d4cad90
PW
213}
214
215/* See documentation in cli-utils.h. */
216
bfd28288
PA
217number_or_range_parser::number_or_range_parser (const char *string)
218{
219 init (string);
220}
221
222/* See documentation in cli-utils.h. */
223
197f0a60 224void
bfd28288 225number_or_range_parser::init (const char *string)
e9cafbcc 226{
bfd28288
PA
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;
197f0a60
TT
232}
233
234/* See documentation in cli-utils.h. */
e9cafbcc 235
197f0a60 236int
bfd28288 237number_or_range_parser::get_number ()
197f0a60 238{
bfd28288 239 if (m_in_range)
71ef29a8
PA
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
bfd28288 246 if (++m_last_retval == m_end_value)
71ef29a8
PA
247 {
248 /* End of range reached; advance token pointer. */
bfd28288
PA
249 m_cur_tok = m_end_ptr;
250 m_in_range = false;
71ef29a8
PA
251 }
252 }
bfd28288 253 else if (*m_cur_tok != '-')
e9cafbcc 254 {
bfd28288 255 /* Default case: state->m_cur_tok is pointing either to a solo
197f0a60 256 number, or to the first number of a range. */
bfd28288 257 m_last_retval = get_number_trailer (&m_cur_tok, '-');
2c722807
PA
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')))
e9cafbcc 270 {
e799154c 271 const char **temp;
e9cafbcc
TT
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
bfd28288 277 temp = &m_end_ptr;
f1735a53
TT
278 m_end_ptr = skip_spaces (m_cur_tok + 1);
279 m_end_value = ::get_number (temp);
bfd28288 280 if (m_end_value < m_last_retval)
e9cafbcc
TT
281 {
282 error (_("inverted range"));
283 }
bfd28288 284 else if (m_end_value == m_last_retval)
e9cafbcc
TT
285 {
286 /* Degenerate range (number1 == number2). Advance the
287 token pointer so that the range will be treated as a
bfd28288
PA
288 single number. */
289 m_cur_tok = m_end_ptr;
e9cafbcc
TT
290 }
291 else
bfd28288 292 m_in_range = true;
e9cafbcc
TT
293 }
294 }
e9cafbcc 295 else
529c08b2
PW
296 {
297 if (isdigit (*(m_cur_tok + 1)))
298 error (_("negative value"));
299 if (*(m_cur_tok + 1) == '$')
300 {
301 /* Convenience variable. */
302 m_last_retval = ::get_number (&m_cur_tok);
303 if (m_last_retval < 0)
304 error (_("negative value"));
305 }
306 }
bfd28288 307 return m_last_retval;
e9cafbcc
TT
308}
309
71ef29a8
PA
310/* See documentation in cli-utils.h. */
311
312void
bfd28288
PA
313number_or_range_parser::setup_range (int start_value, int end_value,
314 const char *end_ptr)
71ef29a8
PA
315{
316 gdb_assert (start_value > 0);
317
bfd28288
PA
318 m_in_range = true;
319 m_end_ptr = end_ptr;
320 m_last_retval = start_value - 1;
321 m_end_value = end_value;
71ef29a8
PA
322}
323
529c08b2
PW
324/* See documentation in cli-utils.h. */
325
326bool
327number_or_range_parser::finished () const
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
aea5b279
MS
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
e799154c 348number_is_in_list (const char *list, int number)
aea5b279
MS
349{
350 if (list == NULL || *list == '\0')
351 return 1;
352
bfd28288 353 number_or_range_parser parser (list);
529c08b2
PW
354
355 if (parser.finished ())
356 error (_("Arguments must be numbers or '$' variables."));
bfd28288 357 while (!parser.finished ())
298f437a 358 {
bfd28288 359 int gotnum = parser.get_number ();
aea5b279 360
298f437a 361 if (gotnum == 0)
529c08b2 362 error (_("Arguments must be numbers or '$' variables."));
298f437a
MS
363 if (gotnum == number)
364 return 1;
365 }
aea5b279
MS
366 return 0;
367}
368
e9cafbcc
TT
369/* See documentation in cli-utils.h. */
370
63160a43
PA
371const char *
372remove_trailing_whitespace (const char *start, const char *s)
c00f8484
KS
373{
374 while (s > start && isspace (*(s - 1)))
375 --s;
376
377 return s;
378}
55aa24fb
SDJ
379
380/* See documentation in cli-utils.h. */
381
cb791d59 382std::string
f1735a53 383extract_arg (const char **arg)
55aa24fb 384{
b5be8ce0 385 const char *result;
55aa24fb
SDJ
386
387 if (!*arg)
cb791d59 388 return std::string ();
55aa24fb
SDJ
389
390 /* Find the start of the argument. */
f1735a53 391 *arg = skip_spaces (*arg);
55aa24fb 392 if (!**arg)
cb791d59 393 return std::string ();
55aa24fb
SDJ
394 result = *arg;
395
396 /* Find the end of the argument. */
f1735a53 397 *arg = skip_to_space (*arg + 1);
55aa24fb
SDJ
398
399 if (result == *arg)
cb791d59 400 return std::string ();
55aa24fb 401
cb791d59 402 return std::string (result, *arg - result);
b5be8ce0
JB
403}
404
405/* See documentation in cli-utils.h. */
406
cb791d59 407std::string
b5be8ce0
JB
408extract_arg (char **arg)
409{
410 const char *arg_const = *arg;
cb791d59 411 std::string result;
55aa24fb 412
f1735a53 413 result = extract_arg (&arg_const);
b5be8ce0
JB
414 *arg += arg_const - *arg;
415 return result;
55aa24fb 416}
e6f0bce7
HZ
417
418/* See documentation in cli-utils.h. */
419
420int
63160a43 421check_for_argument (const char **str, const char *arg, int arg_len)
e6f0bce7
HZ
422{
423 if (strncmp (*str, arg, arg_len) == 0
424 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
425 {
426 *str += arg_len;
cbba3ecd 427 *str = skip_spaces (*str);
e6f0bce7
HZ
428 return 1;
429 }
430 return 0;
431}
529c08b2
PW
432
433/* See documentation in cli-utils.h. */
434
5d707134
PA
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
This page took 0.607294 seconds and 4 git commands to generate.