Make check_for_argument skip whitespace after arg itself
[binutils-gdb.git] / gdb / cli / cli-utils.c
1 /* CLI utilities.
2
3 Copyright (C) 2011-2019 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 static std::string extract_arg_maybe_quoted (const char **arg);
27
28 /* See documentation in cli-utils.h. */
29
30 int
31 get_number_trailer (const char **pp, int trailer)
32 {
33 int retval = 0; /* default */
34 const char *p = *pp;
35 bool negative = false;
36
37 if (*p == '-')
38 {
39 ++p;
40 negative = true;
41 }
42
43 if (*p == '$')
44 {
45 struct value *val = value_from_history_ref (p, &p);
46
47 if (val) /* Value history reference */
48 {
49 if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
50 retval = value_as_long (val);
51 else
52 {
53 printf_filtered (_("History value must have integer type.\n"));
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;
62 const char *start = ++p;
63 LONGEST longest_val;
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';
70 if (get_internalvar_integer (lookup_internalvar (varname),
71 &longest_val))
72 retval = (int) longest_val;
73 else
74 {
75 printf_filtered (_("Convenience variable must "
76 "have integer value.\n"));
77 retval = 0;
78 }
79 }
80 }
81 else
82 {
83 const char *p1 = p;
84 while (*p >= '0' && *p <= '9')
85 ++p;
86 if (p == p1)
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
96 retval = atoi (p1);
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 }
105 p = skip_spaces (p);
106 *pp = p;
107 return negative ? -retval : retval;
108 }
109
110 /* See documentation in cli-utils.h. */
111
112 int
113 get_number (const char **pp)
114 {
115 return get_number_trailer (pp, '\0');
116 }
117
118 /* See documentation in cli-utils.h. */
119
120 int
121 get_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
133 bool
134 extract_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 {
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;
157 return true;
158 }
159
160 return false;
161 }
162
163 /* See documentation in cli-utils.h. */
164
165 void
166 report_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
177 const char *
178 info_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\
183 matches NAMEREGEXP.\n\
184 If -t TYPEREGEXP is provided, only prints the %s whose type\n\
185 matches TYPEREGEXP. Note that the matching is done with the type\n\
186 printed by the 'whatis' command.\n\
187 By default, the command might produce headers and/or messages indicating\n\
188 why no %s can be printed.\n\
189 The 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
195 number_or_range_parser::number_or_range_parser (const char *string)
196 {
197 init (string);
198 }
199
200 /* See documentation in cli-utils.h. */
201
202 void
203 number_or_range_parser::init (const char *string)
204 {
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;
210 }
211
212 /* See documentation in cli-utils.h. */
213
214 int
215 number_or_range_parser::get_number ()
216 {
217 if (m_in_range)
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
224 if (++m_last_retval == m_end_value)
225 {
226 /* End of range reached; advance token pointer. */
227 m_cur_tok = m_end_ptr;
228 m_in_range = false;
229 }
230 }
231 else if (*m_cur_tok != '-')
232 {
233 /* Default case: state->m_cur_tok is pointing either to a solo
234 number, or to the first number of a range. */
235 m_last_retval = get_number_trailer (&m_cur_tok, '-');
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)))
240 {
241 const char **temp;
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
247 temp = &m_end_ptr;
248 m_end_ptr = skip_spaces (m_cur_tok + 1);
249 m_end_value = ::get_number (temp);
250 if (m_end_value < m_last_retval)
251 {
252 error (_("inverted range"));
253 }
254 else if (m_end_value == m_last_retval)
255 {
256 /* Degenerate range (number1 == number2). Advance the
257 token pointer so that the range will be treated as a
258 single number. */
259 m_cur_tok = m_end_ptr;
260 }
261 else
262 m_in_range = true;
263 }
264 }
265 else
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 }
277 return m_last_retval;
278 }
279
280 /* See documentation in cli-utils.h. */
281
282 void
283 number_or_range_parser::setup_range (int start_value, int end_value,
284 const char *end_ptr)
285 {
286 gdb_assert (start_value > 0);
287
288 m_in_range = true;
289 m_end_ptr = end_ptr;
290 m_last_retval = start_value - 1;
291 m_end_value = end_value;
292 }
293
294 /* See documentation in cli-utils.h. */
295
296 bool
297 number_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
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
317 int
318 number_is_in_list (const char *list, int number)
319 {
320 if (list == NULL || *list == '\0')
321 return 1;
322
323 number_or_range_parser parser (list);
324
325 if (parser.finished ())
326 error (_("Arguments must be numbers or '$' variables."));
327 while (!parser.finished ())
328 {
329 int gotnum = parser.get_number ();
330
331 if (gotnum == 0)
332 error (_("Arguments must be numbers or '$' variables."));
333 if (gotnum == number)
334 return 1;
335 }
336 return 0;
337 }
338
339 /* See documentation in cli-utils.h. */
340
341 const char *
342 remove_trailing_whitespace (const char *start, const char *s)
343 {
344 while (s > start && isspace (*(s - 1)))
345 --s;
346
347 return s;
348 }
349
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
356 static std::string
357 extract_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
413 /* See documentation in cli-utils.h. */
414
415 std::string
416 extract_arg (const char **arg)
417 {
418 const char *result;
419
420 if (!*arg)
421 return std::string ();
422
423 /* Find the start of the argument. */
424 *arg = skip_spaces (*arg);
425 if (!**arg)
426 return std::string ();
427 result = *arg;
428
429 /* Find the end of the argument. */
430 *arg = skip_to_space (*arg + 1);
431
432 if (result == *arg)
433 return std::string ();
434
435 return std::string (result, *arg - result);
436 }
437
438 /* See documentation in cli-utils.h. */
439
440 std::string
441 extract_arg (char **arg)
442 {
443 const char *arg_const = *arg;
444 std::string result;
445
446 result = extract_arg (&arg_const);
447 *arg += arg_const - *arg;
448 return result;
449 }
450
451 /* See documentation in cli-utils.h. */
452
453 int
454 check_for_argument (const char **str, const char *arg, int arg_len)
455 {
456 if (strncmp (*str, arg, arg_len) == 0
457 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
458 {
459 *str += arg_len;
460 *str = skip_spaces (*str);
461 return 1;
462 }
463 return 0;
464 }
465
466 /* See documentation in cli-utils.h. */
467
468 int
469 parse_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
496 bool
497 parse_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 }