gdb/python: Use copy-initialization more when possible
[deliverable/binutils-gdb.git] / gdb / cli / cli-utils.c
CommitLineData
e9cafbcc
TT
1/* CLI utilities.
2
e2882c85 3 Copyright (C) 2011-2018 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
5d5658a1 26/* See documentation in cli-utils.h. */
e9cafbcc 27
5d5658a1 28int
e799154c 29get_number_trailer (const char **pp, int trailer)
e9cafbcc
TT
30{
31 int retval = 0; /* default */
e799154c 32 const char *p = *pp;
95e95a6d
PA
33 bool negative = false;
34
35 if (*p == '-')
36 {
37 ++p;
38 negative = true;
39 }
e9cafbcc
TT
40
41 if (*p == '$')
42 {
3bd0f5ef 43 struct value *val = value_from_history_ref (p, &p);
e9cafbcc 44
3bd0f5ef 45 if (val) /* Value history reference */
e9cafbcc 46 {
3bd0f5ef
MS
47 if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
48 retval = value_as_long (val);
49 else
50 {
2217da06 51 printf_filtered (_("History value must have integer type.\n"));
3bd0f5ef
MS
52 retval = 0;
53 }
54 }
55 else /* Convenience variable */
56 {
57 /* Internal variable. Make a copy of the name, so we can
58 null-terminate it to pass to lookup_internalvar(). */
59 char *varname;
e799154c 60 const char *start = ++p;
3bd0f5ef
MS
61 LONGEST val;
62
63 while (isalnum (*p) || *p == '_')
64 p++;
65 varname = (char *) alloca (p - start + 1);
66 strncpy (varname, start, p - start);
67 varname[p - start] = '\0';
68 if (get_internalvar_integer (lookup_internalvar (varname), &val))
69 retval = (int) val;
70 else
71 {
72 printf_filtered (_("Convenience variable must "
73 "have integer value.\n"));
74 retval = 0;
75 }
e9cafbcc
TT
76 }
77 }
78 else
79 {
95e95a6d 80 const char *p1 = p;
e9cafbcc
TT
81 while (*p >= '0' && *p <= '9')
82 ++p;
95e95a6d 83 if (p == p1)
e9cafbcc
TT
84 /* There is no number here. (e.g. "cond a == b"). */
85 {
86 /* Skip non-numeric token. */
87 while (*p && !isspace((int) *p))
88 ++p;
89 /* Return zero, which caller must interpret as error. */
90 retval = 0;
91 }
92 else
95e95a6d 93 retval = atoi (p1);
e9cafbcc
TT
94 }
95 if (!(isspace (*p) || *p == '\0' || *p == trailer))
96 {
97 /* Trailing junk: return 0 and let caller print error msg. */
98 while (!(isspace (*p) || *p == '\0' || *p == trailer))
99 ++p;
100 retval = 0;
101 }
f1735a53 102 p = skip_spaces (p);
e9cafbcc 103 *pp = p;
95e95a6d 104 return negative ? -retval : retval;
e9cafbcc
TT
105}
106
107/* See documentation in cli-utils.h. */
108
109int
f1735a53 110get_number (const char **pp)
e9cafbcc
TT
111{
112 return get_number_trailer (pp, '\0');
113}
114
115/* See documentation in cli-utils.h. */
116
e799154c
TT
117int
118get_number (char **pp)
119{
120 int result;
121 const char *p = *pp;
122
123 result = get_number_trailer (&p, '\0');
124 *pp = (char *) p;
125 return result;
126}
127
128/* See documentation in cli-utils.h. */
129
bfd28288
PA
130number_or_range_parser::number_or_range_parser (const char *string)
131{
132 init (string);
133}
134
135/* See documentation in cli-utils.h. */
136
197f0a60 137void
bfd28288 138number_or_range_parser::init (const char *string)
e9cafbcc 139{
bfd28288
PA
140 m_cur_tok = string;
141 m_last_retval = 0;
142 m_end_value = 0;
143 m_end_ptr = NULL;
144 m_in_range = false;
197f0a60
TT
145}
146
147/* See documentation in cli-utils.h. */
e9cafbcc 148
197f0a60 149int
bfd28288 150number_or_range_parser::get_number ()
197f0a60 151{
bfd28288 152 if (m_in_range)
71ef29a8
PA
153 {
154 /* All number-parsing has already been done. Return the next
155 integer value (one greater than the saved previous value).
156 Do not advance the token pointer until the end of range is
157 reached. */
158
bfd28288 159 if (++m_last_retval == m_end_value)
71ef29a8
PA
160 {
161 /* End of range reached; advance token pointer. */
bfd28288
PA
162 m_cur_tok = m_end_ptr;
163 m_in_range = false;
71ef29a8
PA
164 }
165 }
bfd28288 166 else if (*m_cur_tok != '-')
e9cafbcc 167 {
bfd28288 168 /* Default case: state->m_cur_tok is pointing either to a solo
197f0a60 169 number, or to the first number of a range. */
bfd28288 170 m_last_retval = get_number_trailer (&m_cur_tok, '-');
529c08b2
PW
171 /* If get_number_trailer has found a -, it might be the start
172 of a command option. So, do not parse a range if the - is
173 followed by an alpha. */
174 if (*m_cur_tok == '-' && !isalpha (*(m_cur_tok + 1)))
e9cafbcc 175 {
e799154c 176 const char **temp;
e9cafbcc
TT
177
178 /* This is the start of a range (<number1> - <number2>).
179 Skip the '-', parse and remember the second number,
180 and also remember the end of the final token. */
181
bfd28288 182 temp = &m_end_ptr;
f1735a53
TT
183 m_end_ptr = skip_spaces (m_cur_tok + 1);
184 m_end_value = ::get_number (temp);
bfd28288 185 if (m_end_value < m_last_retval)
e9cafbcc
TT
186 {
187 error (_("inverted range"));
188 }
bfd28288 189 else if (m_end_value == m_last_retval)
e9cafbcc
TT
190 {
191 /* Degenerate range (number1 == number2). Advance the
192 token pointer so that the range will be treated as a
bfd28288
PA
193 single number. */
194 m_cur_tok = m_end_ptr;
e9cafbcc
TT
195 }
196 else
bfd28288 197 m_in_range = true;
e9cafbcc
TT
198 }
199 }
e9cafbcc 200 else
529c08b2
PW
201 {
202 if (isdigit (*(m_cur_tok + 1)))
203 error (_("negative value"));
204 if (*(m_cur_tok + 1) == '$')
205 {
206 /* Convenience variable. */
207 m_last_retval = ::get_number (&m_cur_tok);
208 if (m_last_retval < 0)
209 error (_("negative value"));
210 }
211 }
bfd28288 212 return m_last_retval;
e9cafbcc
TT
213}
214
71ef29a8
PA
215/* See documentation in cli-utils.h. */
216
217void
bfd28288
PA
218number_or_range_parser::setup_range (int start_value, int end_value,
219 const char *end_ptr)
71ef29a8
PA
220{
221 gdb_assert (start_value > 0);
222
bfd28288
PA
223 m_in_range = true;
224 m_end_ptr = end_ptr;
225 m_last_retval = start_value - 1;
226 m_end_value = end_value;
71ef29a8
PA
227}
228
529c08b2
PW
229/* See documentation in cli-utils.h. */
230
231bool
232number_or_range_parser::finished () const
233{
234 /* Parsing is finished when at end of string or null string,
235 or we are not in a range and not in front of an integer, negative
236 integer, convenience var or negative convenience var. */
237 return (m_cur_tok == NULL || *m_cur_tok == '\0'
238 || (!m_in_range
239 && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
240 && !(*m_cur_tok == '-'
241 && (isdigit (m_cur_tok[1]) || m_cur_tok[1] == '$'))));
242}
243
aea5b279
MS
244/* Accept a number and a string-form list of numbers such as is
245 accepted by get_number_or_range. Return TRUE if the number is
246 in the list.
247
248 By definition, an empty list includes all numbers. This is to
249 be interpreted as typing a command such as "delete break" with
250 no arguments. */
251
252int
e799154c 253number_is_in_list (const char *list, int number)
aea5b279
MS
254{
255 if (list == NULL || *list == '\0')
256 return 1;
257
bfd28288 258 number_or_range_parser parser (list);
529c08b2
PW
259
260 if (parser.finished ())
261 error (_("Arguments must be numbers or '$' variables."));
bfd28288 262 while (!parser.finished ())
298f437a 263 {
bfd28288 264 int gotnum = parser.get_number ();
aea5b279 265
298f437a 266 if (gotnum == 0)
529c08b2 267 error (_("Arguments must be numbers or '$' variables."));
298f437a
MS
268 if (gotnum == number)
269 return 1;
270 }
aea5b279
MS
271 return 0;
272}
273
e9cafbcc
TT
274/* See documentation in cli-utils.h. */
275
63160a43
PA
276const char *
277remove_trailing_whitespace (const char *start, const char *s)
c00f8484
KS
278{
279 while (s > start && isspace (*(s - 1)))
280 --s;
281
282 return s;
283}
55aa24fb
SDJ
284
285/* See documentation in cli-utils.h. */
286
cb791d59 287std::string
f1735a53 288extract_arg (const char **arg)
55aa24fb 289{
b5be8ce0 290 const char *result;
55aa24fb
SDJ
291
292 if (!*arg)
cb791d59 293 return std::string ();
55aa24fb
SDJ
294
295 /* Find the start of the argument. */
f1735a53 296 *arg = skip_spaces (*arg);
55aa24fb 297 if (!**arg)
cb791d59 298 return std::string ();
55aa24fb
SDJ
299 result = *arg;
300
301 /* Find the end of the argument. */
f1735a53 302 *arg = skip_to_space (*arg + 1);
55aa24fb
SDJ
303
304 if (result == *arg)
cb791d59 305 return std::string ();
55aa24fb 306
cb791d59 307 return std::string (result, *arg - result);
b5be8ce0
JB
308}
309
310/* See documentation in cli-utils.h. */
311
cb791d59 312std::string
b5be8ce0
JB
313extract_arg (char **arg)
314{
315 const char *arg_const = *arg;
cb791d59 316 std::string result;
55aa24fb 317
f1735a53 318 result = extract_arg (&arg_const);
b5be8ce0
JB
319 *arg += arg_const - *arg;
320 return result;
55aa24fb 321}
e6f0bce7
HZ
322
323/* See documentation in cli-utils.h. */
324
325int
63160a43 326check_for_argument (const char **str, const char *arg, int arg_len)
e6f0bce7
HZ
327{
328 if (strncmp (*str, arg, arg_len) == 0
329 && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
330 {
331 *str += arg_len;
332 return 1;
333 }
334 return 0;
335}
529c08b2
PW
336
337/* See documentation in cli-utils.h. */
338
339int
340parse_flags (const char **str, const char *flags)
341{
342 const char *p = skip_spaces (*str);
343
344 if (p[0] == '-'
345 && isalpha (p[1])
346 && (p[2] == '\0' || isspace (p[2])))
347 {
348 const char pf = p[1];
349 const char *f = flags;
350
351 while (*f != '\0')
352 {
353 if (*f == pf)
354 {
355 *str = skip_spaces (p + 2);
356 return f - flags + 1;
357 }
358 f++;
359 }
360 }
361
362 return 0;
363}
364
365/* See documentation in cli-utils.h. */
366
367bool
368parse_flags_qcs (const char *which_command, const char **str,
369 qcs_flags *flags)
370{
371 switch (parse_flags (str, "qcs"))
372 {
373 case 0:
374 return false;
375 case 1:
376 flags->quiet = true;
377 break;
378 case 2:
379 flags->cont = true;
380 break;
381 case 3:
382 flags->silent = true;
383 break;
384 default:
385 gdb_assert_not_reached ("int qcs flag out of bound");
386 }
387
388 if (flags->cont && flags->silent)
389 error (_("%s: -c and -s are mutually exclusive"), which_command);
390
391 return true;
392}
This page took 0.528976 seconds and 4 git commands to generate.