Automatic date update in version.in
[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 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 }