Make check_for_argument skip whitespace after arg itself
[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
0d4cad90
PW
26static std::string extract_arg_maybe_quoted (const char **arg);
27
5d5658a1 28/* See documentation in cli-utils.h. */
e9cafbcc 29
5d5658a1 30int
e799154c 31get_number_trailer (const char **pp, int trailer)
e9cafbcc
TT
32{
33 int retval = 0; /* default */
e799154c 34 const char *p = *pp;
95e95a6d
PA
35 bool negative = false;
36
37 if (*p == '-')
38 {
39 ++p;
40 negative = true;
41 }
e9cafbcc
TT
42
43 if (*p == '$')
44 {
3bd0f5ef 45 struct value *val = value_from_history_ref (p, &p);
e9cafbcc 46
3bd0f5ef 47 if (val) /* Value history reference */
e9cafbcc 48 {
3bd0f5ef
MS
49 if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
50 retval = value_as_long (val);
51 else
52 {
2217da06 53 printf_filtered (_("History value must have integer type.\n"));
3bd0f5ef
MS
54 retval = 0;
55 }
56 }
57 else /* Convenience variable */
58 {
59 /* Internal variable. Make a copy of the name, so we can
60 null-terminate it to pass to lookup_internalvar(). */
61 char *varname;
e799154c 62 const char *start = ++p;
b926417a 63 LONGEST longest_val;
3bd0f5ef
MS
64
65 while (isalnum (*p) || *p == '_')
66 p++;
67 varname = (char *) alloca (p - start + 1);
68 strncpy (varname, start, p - start);
69 varname[p - start] = '\0';
b926417a
TT
70 if (get_internalvar_integer (lookup_internalvar (varname),
71 &longest_val))
72 retval = (int) longest_val;
3bd0f5ef
MS
73 else
74 {
75 printf_filtered (_("Convenience variable must "
76 "have integer value.\n"));
77 retval = 0;
78 }
e9cafbcc
TT
79 }
80 }
81 else
82 {
95e95a6d 83 const char *p1 = p;
e9cafbcc
TT
84 while (*p >= '0' && *p <= '9')
85 ++p;
95e95a6d 86 if (p == p1)
e9cafbcc
TT
87 /* There is no number here. (e.g. "cond a == b"). */
88 {
89 /* Skip non-numeric token. */
90 while (*p && !isspace((int) *p))
91 ++p;
92 /* Return zero, which caller must interpret as error. */
93 retval = 0;
94 }
95 else
95e95a6d 96 retval = atoi (p1);
e9cafbcc
TT
97 }
98 if (!(isspace (*p) || *p == '\0' || *p == trailer))
99 {
100 /* Trailing junk: return 0 and let caller print error msg. */
101 while (!(isspace (*p) || *p == '\0' || *p == trailer))
102 ++p;
103 retval = 0;
104 }
f1735a53 105 p = skip_spaces (p);
e9cafbcc 106 *pp = p;
95e95a6d 107 return negative ? -retval : retval;
e9cafbcc
TT
108}
109
110/* See documentation in cli-utils.h. */
111
112int
f1735a53 113get_number (const char **pp)
e9cafbcc
TT
114{
115 return get_number_trailer (pp, '\0');
116}
117
118/* See documentation in cli-utils.h. */
119
e799154c
TT
120int
121get_number (char **pp)
122{
123 int result;
124 const char *p = *pp;
125
126 result = get_number_trailer (&p, '\0');
127 *pp = (char *) p;
128 return result;
129}
130
131/* See documentation in cli-utils.h. */
132
0d4cad90
PW
133bool
134extract_info_print_args (const char **args,
135 bool *quiet,
136 std::string *regexp,
137 std::string *t_regexp)
138{
139 /* Check for NAMEREGEXP or -- NAMEREGEXP. */
140 if (**args != '-' || check_for_argument (args, "--", 2))
141 {
0d4cad90
PW
142 *regexp = *args;
143 *args = NULL;
144 return true;
145 }
146
147 if (check_for_argument (args, "-t", 2))
148 {
149 *t_regexp = extract_arg_maybe_quoted (args);
150 *args = skip_spaces (*args);
151 return true;
152 }
153
154 if (check_for_argument (args, "-q", 2))
155 {
156 *quiet = true;
0d4cad90
PW
157 return true;
158 }
159
160 return false;
161}
162
163/* See documentation in cli-utils.h. */
164
165void
166report_unrecognized_option_error (const char *command, const char *args)
167{
168 std::string option = extract_arg (&args);
169
170 error (_("Unrecognized option '%s' to %s command. "
171 "Try \"help %s\"."), option.c_str (),
172 command, command);
173}
174
175/* See documentation in cli-utils.h. */
176
177const char *
178info_print_args_help (const char *prefix,
179 const char *entity_kind)
180{
181 return xstrprintf (_("\
182%sIf NAMEREGEXP is provided, only prints the %s whose name\n\
183matches NAMEREGEXP.\n\
184If -t TYPEREGEXP is provided, only prints the %s whose type\n\
185matches TYPEREGEXP. Note that the matching is done with the type\n\
186printed by the 'whatis' command.\n\
187By default, the command might produce headers and/or messages indicating\n\
188why no %s can be printed.\n\
189The flag -q disables the production of these headers and messages."),
190 prefix, entity_kind, entity_kind, entity_kind);
191}
192
193/* See documentation in cli-utils.h. */
194
bfd28288
PA
195number_or_range_parser::number_or_range_parser (const char *string)
196{
197 init (string);
198}
199
200/* See documentation in cli-utils.h. */
201
197f0a60 202void
bfd28288 203number_or_range_parser::init (const char *string)
e9cafbcc 204{
bfd28288
PA
205 m_cur_tok = string;
206 m_last_retval = 0;
207 m_end_value = 0;
208 m_end_ptr = NULL;
209 m_in_range = false;
197f0a60
TT
210}
211
212/* See documentation in cli-utils.h. */
e9cafbcc 213
197f0a60 214int
bfd28288 215number_or_range_parser::get_number ()
197f0a60 216{
bfd28288 217 if (m_in_range)
71ef29a8
PA
218 {
219 /* All number-parsing has already been done. Return the next
220 integer value (one greater than the saved previous value).
221 Do not advance the token pointer until the end of range is
222 reached. */
223
bfd28288 224 if (++m_last_retval == m_end_value)
71ef29a8
PA
225 {
226 /* End of range reached; advance token pointer. */
bfd28288
PA
227 m_cur_tok = m_end_ptr;
228 m_in_range = false;
71ef29a8
PA
229 }
230 }
bfd28288 231 else if (*m_cur_tok != '-')
e9cafbcc 232 {
bfd28288 233 /* Default case: state->m_cur_tok is pointing either to a solo
197f0a60 234 number, or to the first number of a range. */
bfd28288 235 m_last_retval = get_number_trailer (&m_cur_tok, '-');
529c08b2
PW
236 /* If get_number_trailer has found a -, it might be the start
237 of a command option. So, do not parse a range if the - is
238 followed by an alpha. */
239 if (*m_cur_tok == '-' && !isalpha (*(m_cur_tok + 1)))
e9cafbcc 240 {
e799154c 241 const char **temp;
e9cafbcc
TT
242
243 /* This is the start of a range (<number1> - <number2>).
244 Skip the '-', parse and remember the second number,
245 and also remember the end of the final token. */
246
bfd28288 247 temp = &m_end_ptr;
f1735a53
TT
248 m_end_ptr = skip_spaces (m_cur_tok + 1);
249 m_end_value = ::get_number (temp);
bfd28288 250 if (m_end_value < m_last_retval)
e9cafbcc
TT
251 {
252 error (_("inverted range"));
253 }
bfd28288 254 else if (m_end_value == m_last_retval)
e9cafbcc
TT
255 {
256 /* Degenerate range (number1 == number2). Advance the
257 token pointer so that the range will be treated as a
bfd28288
PA
258 single number. */
259 m_cur_tok = m_end_ptr;
e9cafbcc
TT
260 }
261 else
bfd28288 262 m_in_range = true;
e9cafbcc
TT
263 }
264 }
e9cafbcc 265 else
529c08b2
PW
266 {
267 if (isdigit (*(m_cur_tok + 1)))
268 error (_("negative value"));
269 if (*(m_cur_tok + 1) == '$')
270 {
271 /* Convenience variable. */
272 m_last_retval = ::get_number (&m_cur_tok);
273 if (m_last_retval < 0)
274 error (_("negative value"));
275 }
276 }
bfd28288 277 return m_last_retval;
e9cafbcc
TT
278}
279
71ef29a8
PA
280/* See documentation in cli-utils.h. */
281
282void
bfd28288
PA
283number_or_range_parser::setup_range (int start_value, int end_value,
284 const char *end_ptr)
71ef29a8
PA
285{
286 gdb_assert (start_value > 0);
287
bfd28288
PA
288 m_in_range = true;
289 m_end_ptr = end_ptr;
290 m_last_retval = start_value - 1;
291 m_end_value = end_value;
71ef29a8
PA
292}
293
529c08b2
PW
294/* See documentation in cli-utils.h. */
295
296bool
297number_or_range_parser::finished () const
298{
299 /* Parsing is finished when at end of string or null string,
300 or we are not in a range and not in front of an integer, negative
301 integer, convenience var or negative convenience var. */
302 return (m_cur_tok == NULL || *m_cur_tok == '\0'
303 || (!m_in_range
304 && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
305 && !(*m_cur_tok == '-'
306 && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
307}
308
aea5b279
MS
309/* Accept a number and a string-form list of numbers such as is
310 accepted by get_number_or_range. Return TRUE if the number is
311 in the list.
312
313 By definition, an empty list includes all numbers. This is to
314 be interpreted as typing a command such as "delete break" with
315 no arguments. */
316
317int
e799154c 318number_is_in_list (const char *list, int number)
aea5b279
MS
319{
320 if (list == NULL || *list == '\0')
321 return 1;
322
bfd28288 323 number_or_range_parser parser (list);
529c08b2
PW
324
325 if (parser.finished ())
326 error (_("Arguments must be numbers or '$' variables."));
bfd28288 327 while (!parser.finished ())
298f437a 328 {
bfd28288 329 int gotnum = parser.get_number ();
aea5b279 330
298f437a 331 if (gotnum == 0)
529c08b2 332 error (_("Arguments must be numbers or '$' variables."));
298f437a
MS
333 if (gotnum == number)
334 return 1;
335 }
aea5b279
MS
336 return 0;
337}
338
e9cafbcc
TT
339/* See documentation in cli-utils.h. */
340
63160a43
PA
341const char *
342remove_trailing_whitespace (const char *start, const char *s)
c00f8484
KS
343{
344 while (s > start && isspace (*(s - 1)))
345 --s;
346
347 return s;
348}
55aa24fb 349
0d4cad90
PW
350/* A helper function to extract an argument from *ARG. An argument is
351 delimited by whitespace, but it can also be optionally quoted.
352 The quoting and special characters are handled similarly to
353 the parsing done by gdb_argv.
354 The return value is empty if no argument was found. */
355
356static std::string
357extract_arg_maybe_quoted (const char **arg)
358{
359 bool squote = false;
360 bool dquote = false;
361 bool bsquote = false;
362 std::string result;
363 const char *p = *arg;
364
365 /* Find the start of the argument. */
366 p = skip_spaces (p);
367
368 /* Parse p similarly to gdb_argv buildargv function. */
369 while (*p != '\0')
370 {
371 if (isspace (*p) && !squote && !dquote && !bsquote)
372 break;
373 else
374 {
375 if (bsquote)
376 {
377 bsquote = false;
378 result += *p;
379 }
380 else if (*p == '\\')
381 bsquote = true;
382 else if (squote)
383 {
384 if (*p == '\'')
385 squote = false;
386 else
387 result += *p;
388 }
389 else if (dquote)
390 {
391 if (*p == '"')
392 dquote = false;
393 else
394 result += *p;
395 }
396 else
397 {
398 if (*p == '\'')
399 squote = true;
400 else if (*p == '"')
401 dquote = true;
402 else
403 result += *p;
404 }
405 p++;
406 }
407 }
408
409 *arg = p;
410 return result;
411}
412
55aa24fb
SDJ
413/* See documentation in cli-utils.h. */
414
cb791d59 415std::string
f1735a53 416extract_arg (const char **arg)
55aa24fb 417{
b5be8ce0 418 const char *result;
55aa24fb
SDJ
419
420 if (!*arg)
cb791d59 421 return std::string ();
55aa24fb
SDJ
422
423 /* Find the start of the argument. */
f1735a53 424 *arg = skip_spaces (*arg);
55aa24fb 425 if (!**arg)
cb791d59 426 return std::string ();
55aa24fb
SDJ
427 result = *arg;
428
429 /* Find the end of the argument. */
f1735a53 430 *arg = skip_to_space (*arg + 1);
55aa24fb
SDJ
431
432 if (result == *arg)
cb791d59 433 return std::string ();
55aa24fb 434
cb791d59 435 return std::string (result, *arg - result);
b5be8ce0
JB
436}
437
438/* See documentation in cli-utils.h. */
439
cb791d59 440std::string
b5be8ce0
JB
441extract_arg (char **arg)
442{
443 const char *arg_const = *arg;
cb791d59 444 std::string result;
55aa24fb 445
f1735a53 446 result = extract_arg (&arg_const);
b5be8ce0
JB
447 *arg += arg_const - *arg;
448 return result;
55aa24fb 449}
e6f0bce7
HZ
450
451/* See documentation in cli-utils.h. */
452
453int
63160a43 454check_for_argument (const char **str, const char *arg, int arg_len)
e6f0bce7
HZ
455{
456 if (strncmp (*str, arg, arg_len) == 0
457 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
458 {
459 *str += arg_len;
cbba3ecd 460 *str = skip_spaces (*str);
e6f0bce7
HZ
461 return 1;
462 }
463 return 0;
464}
529c08b2
PW
465
466/* See documentation in cli-utils.h. */
467
468int
469parse_flags (const char **str, const char *flags)
470{
471 const char *p = skip_spaces (*str);
472
473 if (p[0] == '-'
474 && isalpha (p[1])
475 && (p[2] == '\0' || isspace (p[2])))
476 {
477 const char pf = p[1];
478 const char *f = flags;
479
480 while (*f != '\0')
481 {
482 if (*f == pf)
483 {
484 *str = skip_spaces (p + 2);
485 return f - flags + 1;
486 }
487 f++;
488 }
489 }
490
491 return 0;
492}
493
494/* See documentation in cli-utils.h. */
495
496bool
497parse_flags_qcs (const char *which_command, const char **str,
498 qcs_flags *flags)
499{
500 switch (parse_flags (str, "qcs"))
501 {
502 case 0:
503 return false;
504 case 1:
505 flags->quiet = true;
506 break;
507 case 2:
508 flags->cont = true;
509 break;
510 case 3:
511 flags->silent = true;
512 break;
513 default:
514 gdb_assert_not_reached ("int qcs flag out of bound");
515 }
516
517 if (flags->cont && flags->silent)
518 error (_("%s: -c and -s are mutually exclusive"), which_command);
519
520 return true;
521}
This page took 0.567992 seconds and 4 git commands to generate.