Reading signal handler frame in AIX
[deliverable/binutils-gdb.git] / gdb / cli / cli-utils.c
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 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 *args = skip_spaces (*args);
143 *regexp = *args;
144 *args = NULL;
145 return true;
146 }
147
148 if (check_for_argument (args, "-t", 2))
149 {
150 *t_regexp = extract_arg_maybe_quoted (args);
151 *args = skip_spaces (*args);
152 return true;
153 }
154
155 if (check_for_argument (args, "-q", 2))
156 {
157 *quiet = true;
158 *args = skip_spaces (*args);
159 return true;
160 }
161
162 return false;
163 }
164
165 /* See documentation in cli-utils.h. */
166
167 void
168 report_unrecognized_option_error (const char *command, const char *args)
169 {
170 std::string option = extract_arg (&args);
171
172 error (_("Unrecognized option '%s' to %s command. "
173 "Try \"help %s\"."), option.c_str (),
174 command, command);
175 }
176
177 /* See documentation in cli-utils.h. */
178
179 const char *
180 info_print_args_help (const char *prefix,
181 const char *entity_kind)
182 {
183 return xstrprintf (_("\
184 %sIf NAMEREGEXP is provided, only prints the %s whose name\n\
185 matches NAMEREGEXP.\n\
186 If -t TYPEREGEXP is provided, only prints the %s whose type\n\
187 matches TYPEREGEXP. Note that the matching is done with the type\n\
188 printed by the 'whatis' command.\n\
189 By default, the command might produce headers and/or messages indicating\n\
190 why no %s can be printed.\n\
191 The flag -q disables the production of these headers and messages."),
192 prefix, entity_kind, entity_kind, entity_kind);
193 }
194
195 /* See documentation in cli-utils.h. */
196
197 number_or_range_parser::number_or_range_parser (const char *string)
198 {
199 init (string);
200 }
201
202 /* See documentation in cli-utils.h. */
203
204 void
205 number_or_range_parser::init (const char *string)
206 {
207 m_cur_tok = string;
208 m_last_retval = 0;
209 m_end_value = 0;
210 m_end_ptr = NULL;
211 m_in_range = false;
212 }
213
214 /* See documentation in cli-utils.h. */
215
216 int
217 number_or_range_parser::get_number ()
218 {
219 if (m_in_range)
220 {
221 /* All number-parsing has already been done. Return the next
222 integer value (one greater than the saved previous value).
223 Do not advance the token pointer until the end of range is
224 reached. */
225
226 if (++m_last_retval == m_end_value)
227 {
228 /* End of range reached; advance token pointer. */
229 m_cur_tok = m_end_ptr;
230 m_in_range = false;
231 }
232 }
233 else if (*m_cur_tok != '-')
234 {
235 /* Default case: state->m_cur_tok is pointing either to a solo
236 number, or to the first number of a range. */
237 m_last_retval = get_number_trailer (&m_cur_tok, '-');
238 /* If get_number_trailer has found a -, it might be the start
239 of a command option. So, do not parse a range if the - is
240 followed by an alpha. */
241 if (*m_cur_tok == '-' && !isalpha (*(m_cur_tok + 1)))
242 {
243 const char **temp;
244
245 /* This is the start of a range (<number1> - <number2>).
246 Skip the '-', parse and remember the second number,
247 and also remember the end of the final token. */
248
249 temp = &m_end_ptr;
250 m_end_ptr = skip_spaces (m_cur_tok + 1);
251 m_end_value = ::get_number (temp);
252 if (m_end_value < m_last_retval)
253 {
254 error (_("inverted range"));
255 }
256 else if (m_end_value == m_last_retval)
257 {
258 /* Degenerate range (number1 == number2). Advance the
259 token pointer so that the range will be treated as a
260 single number. */
261 m_cur_tok = m_end_ptr;
262 }
263 else
264 m_in_range = true;
265 }
266 }
267 else
268 {
269 if (isdigit (*(m_cur_tok + 1)))
270 error (_("negative value"));
271 if (*(m_cur_tok + 1) == '$')
272 {
273 /* Convenience variable. */
274 m_last_retval = ::get_number (&m_cur_tok);
275 if (m_last_retval < 0)
276 error (_("negative value"));
277 }
278 }
279 return m_last_retval;
280 }
281
282 /* See documentation in cli-utils.h. */
283
284 void
285 number_or_range_parser::setup_range (int start_value, int end_value,
286 const char *end_ptr)
287 {
288 gdb_assert (start_value > 0);
289
290 m_in_range = true;
291 m_end_ptr = end_ptr;
292 m_last_retval = start_value - 1;
293 m_end_value = end_value;
294 }
295
296 /* See documentation in cli-utils.h. */
297
298 bool
299 number_or_range_parser::finished () const
300 {
301 /* Parsing is finished when at end of string or null string,
302 or we are not in a range and not in front of an integer, negative
303 integer, convenience var or negative convenience var. */
304 return (m_cur_tok == NULL || *m_cur_tok == '\0'
305 || (!m_in_range
306 && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
307 && !(*m_cur_tok == '-'
308 && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
309 }
310
311 /* Accept a number and a string-form list of numbers such as is
312 accepted by get_number_or_range. Return TRUE if the number is
313 in the list.
314
315 By definition, an empty list includes all numbers. This is to
316 be interpreted as typing a command such as "delete break" with
317 no arguments. */
318
319 int
320 number_is_in_list (const char *list, int number)
321 {
322 if (list == NULL || *list == '\0')
323 return 1;
324
325 number_or_range_parser parser (list);
326
327 if (parser.finished ())
328 error (_("Arguments must be numbers or '$' variables."));
329 while (!parser.finished ())
330 {
331 int gotnum = parser.get_number ();
332
333 if (gotnum == 0)
334 error (_("Arguments must be numbers or '$' variables."));
335 if (gotnum == number)
336 return 1;
337 }
338 return 0;
339 }
340
341 /* See documentation in cli-utils.h. */
342
343 const char *
344 remove_trailing_whitespace (const char *start, const char *s)
345 {
346 while (s > start && isspace (*(s - 1)))
347 --s;
348
349 return s;
350 }
351
352 /* A helper function to extract an argument from *ARG. An argument is
353 delimited by whitespace, but it can also be optionally quoted.
354 The quoting and special characters are handled similarly to
355 the parsing done by gdb_argv.
356 The return value is empty if no argument was found. */
357
358 static std::string
359 extract_arg_maybe_quoted (const char **arg)
360 {
361 bool squote = false;
362 bool dquote = false;
363 bool bsquote = false;
364 std::string result;
365 const char *p = *arg;
366
367 /* Find the start of the argument. */
368 p = skip_spaces (p);
369
370 /* Parse p similarly to gdb_argv buildargv function. */
371 while (*p != '\0')
372 {
373 if (isspace (*p) && !squote && !dquote && !bsquote)
374 break;
375 else
376 {
377 if (bsquote)
378 {
379 bsquote = false;
380 result += *p;
381 }
382 else if (*p == '\\')
383 bsquote = true;
384 else if (squote)
385 {
386 if (*p == '\'')
387 squote = false;
388 else
389 result += *p;
390 }
391 else if (dquote)
392 {
393 if (*p == '"')
394 dquote = false;
395 else
396 result += *p;
397 }
398 else
399 {
400 if (*p == '\'')
401 squote = true;
402 else if (*p == '"')
403 dquote = true;
404 else
405 result += *p;
406 }
407 p++;
408 }
409 }
410
411 *arg = p;
412 return result;
413 }
414
415 /* See documentation in cli-utils.h. */
416
417 std::string
418 extract_arg (const char **arg)
419 {
420 const char *result;
421
422 if (!*arg)
423 return std::string ();
424
425 /* Find the start of the argument. */
426 *arg = skip_spaces (*arg);
427 if (!**arg)
428 return std::string ();
429 result = *arg;
430
431 /* Find the end of the argument. */
432 *arg = skip_to_space (*arg + 1);
433
434 if (result == *arg)
435 return std::string ();
436
437 return std::string (result, *arg - result);
438 }
439
440 /* See documentation in cli-utils.h. */
441
442 std::string
443 extract_arg (char **arg)
444 {
445 const char *arg_const = *arg;
446 std::string result;
447
448 result = extract_arg (&arg_const);
449 *arg += arg_const - *arg;
450 return result;
451 }
452
453 /* See documentation in cli-utils.h. */
454
455 int
456 check_for_argument (const char **str, const char *arg, int arg_len)
457 {
458 if (strncmp (*str, arg, arg_len) == 0
459 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
460 {
461 *str += arg_len;
462 return 1;
463 }
464 return 0;
465 }
466
467 /* See documentation in cli-utils.h. */
468
469 int
470 parse_flags (const char **str, const char *flags)
471 {
472 const char *p = skip_spaces (*str);
473
474 if (p[0] == '-'
475 && isalpha (p[1])
476 && (p[2] == '\0' || isspace (p[2])))
477 {
478 const char pf = p[1];
479 const char *f = flags;
480
481 while (*f != '\0')
482 {
483 if (*f == pf)
484 {
485 *str = skip_spaces (p + 2);
486 return f - flags + 1;
487 }
488 f++;
489 }
490 }
491
492 return 0;
493 }
494
495 /* See documentation in cli-utils.h. */
496
497 bool
498 parse_flags_qcs (const char *which_command, const char **str,
499 qcs_flags *flags)
500 {
501 switch (parse_flags (str, "qcs"))
502 {
503 case 0:
504 return false;
505 case 1:
506 flags->quiet = true;
507 break;
508 case 2:
509 flags->cont = true;
510 break;
511 case 3:
512 flags->silent = true;
513 break;
514 default:
515 gdb_assert_not_reached ("int qcs flag out of bound");
516 }
517
518 if (flags->cont && flags->silent)
519 error (_("%s: -c and -s are mutually exclusive"), which_command);
520
521 return true;
522 }
This page took 0.05489 seconds and 4 git commands to generate.