cd3dfe65a2b63b0d4bdf9f8e2fb0d1b91ad64ffe
[external/binutils.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 /* See documentation in cli-utils.h.  */
27
28 ULONGEST
29 get_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     {
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
80 int
81 get_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 (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
100             retval = value_as_long (val);
101           else
102             {
103               printf_filtered (_("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';
120           if (get_internalvar_integer (lookup_internalvar (varname),
121                                        &longest_val))
122             retval = (int) longest_val;
123           else
124             {
125               printf_filtered (_("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
162 int
163 get_number (const char **pp)
164 {
165   return get_number_trailer (pp, '\0');
166 }
167
168 /* See documentation in cli-utils.h.  */
169
170 int
171 get_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
183 void
184 report_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
195 const char *
196 info_print_args_help (const char *prefix,
197                       const char *entity_kind)
198 {
199   return xstrprintf (_("\
200 %sIf NAMEREGEXP is provided, only prints the %s whose name\n\
201 matches NAMEREGEXP.\n\
202 If -t TYPEREGEXP is provided, only prints the %s whose type\n\
203 matches TYPEREGEXP.  Note that the matching is done with the type\n\
204 printed by the 'whatis' command.\n\
205 By default, the command might produce headers and/or messages indicating\n\
206 why no %s can be printed.\n\
207 The flag -q disables the production of these headers and messages."),
208                      prefix, entity_kind, entity_kind, entity_kind);
209 }
210
211 /* See documentation in cli-utils.h.  */
212
213 number_or_range_parser::number_or_range_parser (const char *string)
214 {
215   init (string);
216 }
217
218 /* See documentation in cli-utils.h.  */
219
220 void
221 number_or_range_parser::init (const char *string)
222 {
223   m_cur_tok = string;
224   m_last_retval = 0;
225   m_end_value = 0;
226   m_end_ptr = NULL;
227   m_in_range = false;
228 }
229
230 /* See documentation in cli-utils.h.  */
231
232 int
233 number_or_range_parser::get_number ()
234 {
235   if (m_in_range)
236     {
237       /* All number-parsing has already been done.  Return the next
238          integer value (one greater than the saved previous value).
239          Do not advance the token pointer until the end of range is
240          reached.  */
241
242       if (++m_last_retval == m_end_value)
243         {
244           /* End of range reached; advance token pointer.  */
245           m_cur_tok = m_end_ptr;
246           m_in_range = false;
247         }
248     }
249   else if (*m_cur_tok != '-')
250     {
251       /* Default case: state->m_cur_tok is pointing either to a solo
252          number, or to the first number of a range.  */
253       m_last_retval = get_number_trailer (&m_cur_tok, '-');
254       /* If get_number_trailer has found a '-' preceded by a space, it
255          might be the start of a command option.  So, do not parse a
256          range if the '-' is followed by an alpha or another '-'.  We
257          might also be completing something like
258          "frame apply level 0 -" and we prefer treating that "-" as an
259          option rather than an incomplete range, so check for end of
260          string as well.  */
261       if (m_cur_tok[0] == '-'
262           && !(isspace (m_cur_tok[-1])
263                && (isalpha (m_cur_tok[1])
264                    || m_cur_tok[1] == '-'
265                    || m_cur_tok[1] == '\0')))
266         {
267           const char **temp;
268
269           /* This is the start of a range (<number1> - <number2>).
270              Skip the '-', parse and remember the second number,
271              and also remember the end of the final token.  */
272
273           temp = &m_end_ptr;
274           m_end_ptr = skip_spaces (m_cur_tok + 1);
275           m_end_value = ::get_number (temp);
276           if (m_end_value < m_last_retval)
277             {
278               error (_("inverted range"));
279             }
280           else if (m_end_value == m_last_retval)
281             {
282               /* Degenerate range (number1 == number2).  Advance the
283                  token pointer so that the range will be treated as a
284                  single number.  */
285               m_cur_tok = m_end_ptr;
286             }
287           else
288             m_in_range = true;
289         }
290     }
291   else
292     {
293       if (isdigit (*(m_cur_tok + 1)))
294         error (_("negative value"));
295       if (*(m_cur_tok + 1) == '$')
296         {
297           /* Convenience variable.  */
298           m_last_retval = ::get_number (&m_cur_tok);
299           if (m_last_retval < 0)
300             error (_("negative value"));
301         }
302     }
303   return m_last_retval;
304 }
305
306 /* See documentation in cli-utils.h.  */
307
308 void
309 number_or_range_parser::setup_range (int start_value, int end_value,
310                                      const char *end_ptr)
311 {
312   gdb_assert (start_value > 0);
313
314   m_in_range = true;
315   m_end_ptr = end_ptr;
316   m_last_retval = start_value - 1;
317   m_end_value = end_value;
318 }
319
320 /* See documentation in cli-utils.h.  */
321
322 bool
323 number_or_range_parser::finished () const
324 {
325   /* Parsing is finished when at end of string or null string,
326      or we are not in a range and not in front of an integer, negative
327      integer, convenience var or negative convenience var.  */
328   return (m_cur_tok == NULL || *m_cur_tok == '\0'
329           || (!m_in_range
330               && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
331               && !(*m_cur_tok == '-'
332                    && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
333 }
334
335 /* Accept a number and a string-form list of numbers such as is 
336    accepted by get_number_or_range.  Return TRUE if the number is
337    in the list.
338
339    By definition, an empty list includes all numbers.  This is to 
340    be interpreted as typing a command such as "delete break" with 
341    no arguments.  */
342
343 int
344 number_is_in_list (const char *list, int number)
345 {
346   if (list == NULL || *list == '\0')
347     return 1;
348
349   number_or_range_parser parser (list);
350
351   if (parser.finished ())
352     error (_("Arguments must be numbers or '$' variables."));
353   while (!parser.finished ())
354     {
355       int gotnum = parser.get_number ();
356
357       if (gotnum == 0)
358         error (_("Arguments must be numbers or '$' variables."));
359       if (gotnum == number)
360         return 1;
361     }
362   return 0;
363 }
364
365 /* See documentation in cli-utils.h.  */
366
367 const char *
368 remove_trailing_whitespace (const char *start, const char *s)
369 {
370   while (s > start && isspace (*(s - 1)))
371     --s;
372
373   return s;
374 }
375
376 /* See documentation in cli-utils.h.  */
377
378 std::string
379 extract_arg (const char **arg)
380 {
381   const char *result;
382
383   if (!*arg)
384     return std::string ();
385
386   /* Find the start of the argument.  */
387   *arg = skip_spaces (*arg);
388   if (!**arg)
389     return std::string ();
390   result = *arg;
391
392   /* Find the end of the argument.  */
393   *arg = skip_to_space (*arg + 1);
394
395   if (result == *arg)
396     return std::string ();
397
398   return std::string (result, *arg - result);
399 }
400
401 /* See documentation in cli-utils.h.  */
402
403 std::string
404 extract_arg (char **arg)
405 {
406   const char *arg_const = *arg;
407   std::string result;
408
409   result = extract_arg (&arg_const);
410   *arg += arg_const - *arg;
411   return result;
412 }
413
414 /* See documentation in cli-utils.h.  */
415
416 int
417 check_for_argument (const char **str, const char *arg, int arg_len)
418 {
419   if (strncmp (*str, arg, arg_len) == 0
420       && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
421     {
422       *str += arg_len;
423       *str = skip_spaces (*str);
424       return 1;
425     }
426   return 0;
427 }
428
429 /* See documentation in cli-utils.h.  */
430
431 void
432 validate_flags_qcs (const char *which_command, qcs_flags *flags)
433 {
434   if (flags->cont && flags->silent)
435     error (_("%s: -c and -s are mutually exclusive"), which_command);
436 }
437
438 /* The options used by the 'info variables' commands and similar.  */
439
440 static const gdb::option::option_def info_print_options_defs[] = {
441   gdb::option::boolean_option_def<info_print_options> {
442     "q",
443     [] (info_print_options *opt) { return &opt->quiet; },
444     nullptr, /* show_cmd_cb */
445     nullptr /* set_doc */
446   },
447
448   gdb::option::string_option_def<info_print_options> {
449     "t",
450     [] (info_print_options *opt) { return &opt->type_regexp; },
451     nullptr, /* show_cmd_cb */
452     nullptr /* set_doc */
453   }
454 };
455
456 /* Returns the option group used by 'info variables' and similar.  */
457
458 static gdb::option::option_def_group
459 make_info_print_options_def_group (info_print_options *opts)
460 {
461   return {{info_print_options_defs}, opts};
462 }
463
464 /* See documentation in cli-utils.h.  */
465
466 void
467 extract_info_print_options (info_print_options *opts,
468                             const char **args)
469 {
470   auto grp = make_info_print_options_def_group (opts);
471   gdb::option::process_options
472     (args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
473   if (*args != nullptr && **args == '\0')
474     *args = nullptr;
475 }