3 Copyright (C) 2011-2021 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
21 #include "cli/cli-utils.h"
26 /* See documentation in cli-utils.h. */
29 get_ulongest (const char **pp
, int trailer
)
31 LONGEST retval
= 0; /* default */
36 value
*val
= value_from_history_ref (p
, &p
);
38 if (val
!= NULL
) /* Value history reference */
40 if (value_type (val
)->code () == TYPE_CODE_INT
)
41 retval
= value_as_long (val
);
43 error (_("History value must have integer type."));
45 else /* Convenience variable */
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
== '_')
52 std::string
varname (start
, p
- start
);
53 if (!get_internalvar_integer (lookup_internalvar (varname
.c_str ()),
55 error (_("Convenience variable $%s does not have integer value."),
62 retval
= strtoulst (p
, &end
, 0);
65 /* There is no number here. (e.g. "cond a == b"). */
66 error (_("Expected integer at: %s"), p
);
71 if (!(isspace (*p
) || *p
== '\0' || *p
== trailer
))
72 error (_("Trailing junk at: %s"), p
);
78 /* See documentation in cli-utils.h. */
81 get_number_trailer (const char **pp
, int trailer
)
83 int retval
= 0; /* default */
85 bool negative
= false;
95 struct value
*val
= value_from_history_ref (p
, &p
);
97 if (val
) /* Value history reference */
99 if (value_type (val
)->code () == TYPE_CODE_INT
)
100 retval
= value_as_long (val
);
103 printf_filtered (_("History value must have integer type.\n"));
107 else /* Convenience variable */
109 /* Internal variable. Make a copy of the name, so we can
110 null-terminate it to pass to lookup_internalvar(). */
112 const char *start
= ++p
;
115 while (isalnum (*p
) || *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
),
122 retval
= (int) longest_val
;
125 printf_filtered (_("Convenience variable must "
126 "have integer value.\n"));
134 while (*p
>= '0' && *p
<= '9')
137 /* There is no number here. (e.g. "cond a == b"). */
139 /* Skip non-numeric token. */
140 while (*p
&& !isspace((int) *p
))
142 /* Return zero, which caller must interpret as error. */
148 if (!(isspace (*p
) || *p
== '\0' || *p
== trailer
))
150 /* Trailing junk: return 0 and let caller print error msg. */
151 while (!(isspace (*p
) || *p
== '\0' || *p
== trailer
))
157 return negative
? -retval
: retval
;
160 /* See documentation in cli-utils.h. */
163 get_number (const char **pp
)
165 return get_number_trailer (pp
, '\0');
168 /* See documentation in cli-utils.h. */
171 get_number (char **pp
)
176 result
= get_number_trailer (&p
, '\0');
181 /* See documentation in cli-utils.h. */
184 report_unrecognized_option_error (const char *command
, const char *args
)
186 std::string option
= extract_arg (&args
);
188 error (_("Unrecognized option '%s' to %s command. "
189 "Try \"help %s\"."), option
.c_str (),
193 /* See documentation in cli-utils.h. */
196 info_print_args_help (const char *prefix
,
197 const char *entity_kind
,
198 bool document_n_flag
)
200 return xstrprintf (_("\
201 %sIf NAMEREGEXP is provided, only prints the %s whose name\n\
202 matches NAMEREGEXP.\n\
203 If -t TYPEREGEXP is provided, only prints the %s whose type\n\
204 matches TYPEREGEXP. Note that the matching is done with the type\n\
205 printed by the 'whatis' command.\n\
206 By default, the command might produce headers and/or messages indicating\n\
207 why no %s can be printed.\n\
208 The flag -q disables the production of these headers and messages.%s"),
209 prefix
, entity_kind
, entity_kind
, entity_kind
,
210 (document_n_flag
? _("\n\
211 By default, the command will include non-debug symbols in the output;\n\
212 these can be excluded using the -n flag.") : ""));
215 /* See documentation in cli-utils.h. */
217 number_or_range_parser::number_or_range_parser (const char *string
)
222 /* See documentation in cli-utils.h. */
225 number_or_range_parser::init (const char *string
)
234 /* See documentation in cli-utils.h. */
237 number_or_range_parser::get_number ()
241 /* All number-parsing has already been done. Return the next
242 integer value (one greater than the saved previous value).
243 Do not advance the token pointer until the end of range is
246 if (++m_last_retval
== m_end_value
)
248 /* End of range reached; advance token pointer. */
249 m_cur_tok
= m_end_ptr
;
253 else if (*m_cur_tok
!= '-')
255 /* Default case: state->m_cur_tok is pointing either to a solo
256 number, or to the first number of a range. */
257 m_last_retval
= get_number_trailer (&m_cur_tok
, '-');
258 /* If get_number_trailer has found a '-' preceded by a space, it
259 might be the start of a command option. So, do not parse a
260 range if the '-' is followed by an alpha or another '-'. We
261 might also be completing something like
262 "frame apply level 0 -" and we prefer treating that "-" as an
263 option rather than an incomplete range, so check for end of
265 if (m_cur_tok
[0] == '-'
266 && !(isspace (m_cur_tok
[-1])
267 && (isalpha (m_cur_tok
[1])
268 || m_cur_tok
[1] == '-'
269 || m_cur_tok
[1] == '\0')))
273 /* This is the start of a range (<number1> - <number2>).
274 Skip the '-', parse and remember the second number,
275 and also remember the end of the final token. */
278 m_end_ptr
= skip_spaces (m_cur_tok
+ 1);
279 m_end_value
= ::get_number (temp
);
280 if (m_end_value
< m_last_retval
)
282 error (_("inverted range"));
284 else if (m_end_value
== m_last_retval
)
286 /* Degenerate range (number1 == number2). Advance the
287 token pointer so that the range will be treated as a
289 m_cur_tok
= m_end_ptr
;
297 if (isdigit (*(m_cur_tok
+ 1)))
298 error (_("negative value"));
299 if (*(m_cur_tok
+ 1) == '$')
301 /* Convenience variable. */
302 m_last_retval
= ::get_number (&m_cur_tok
);
303 if (m_last_retval
< 0)
304 error (_("negative value"));
307 return m_last_retval
;
310 /* See documentation in cli-utils.h. */
313 number_or_range_parser::setup_range (int start_value
, int end_value
,
316 gdb_assert (start_value
> 0);
320 m_last_retval
= start_value
- 1;
321 m_end_value
= end_value
;
324 /* See documentation in cli-utils.h. */
327 number_or_range_parser::finished () const
329 /* Parsing is finished when at end of string or null string,
330 or we are not in a range and not in front of an integer, negative
331 integer, convenience var or negative convenience var. */
332 return (m_cur_tok
== NULL
|| *m_cur_tok
== '\0'
334 && !(isdigit (*m_cur_tok
) || *m_cur_tok
== '$')
335 && !(*m_cur_tok
== '-'
336 && (isdigit (m_cur_tok
[1]) || m_cur_tok
[1] == '$'))));
339 /* Accept a number and a string-form list of numbers such as is
340 accepted by get_number_or_range. Return TRUE if the number is
343 By definition, an empty list includes all numbers. This is to
344 be interpreted as typing a command such as "delete break" with
348 number_is_in_list (const char *list
, int number
)
350 if (list
== NULL
|| *list
== '\0')
353 number_or_range_parser
parser (list
);
355 if (parser
.finished ())
356 error (_("Arguments must be numbers or '$' variables."));
357 while (!parser
.finished ())
359 int gotnum
= parser
.get_number ();
362 error (_("Arguments must be numbers or '$' variables."));
363 if (gotnum
== number
)
369 /* See documentation in cli-utils.h. */
372 remove_trailing_whitespace (const char *start
, const char *s
)
374 while (s
> start
&& isspace (*(s
- 1)))
380 /* See documentation in cli-utils.h. */
383 extract_arg (const char **arg
)
388 return std::string ();
390 /* Find the start of the argument. */
391 *arg
= skip_spaces (*arg
);
393 return std::string ();
396 /* Find the end of the argument. */
397 *arg
= skip_to_space (*arg
+ 1);
400 return std::string ();
402 return std::string (result
, *arg
- result
);
405 /* See documentation in cli-utils.h. */
408 extract_arg (char **arg
)
410 const char *arg_const
= *arg
;
413 result
= extract_arg (&arg_const
);
414 *arg
+= arg_const
- *arg
;
418 /* See documentation in cli-utils.h. */
421 check_for_argument (const char **str
, const char *arg
, int arg_len
)
423 if (strncmp (*str
, arg
, arg_len
) == 0
424 && ((*str
)[arg_len
] == '\0' || isspace ((*str
)[arg_len
])))
427 *str
= skip_spaces (*str
);
433 /* See documentation in cli-utils.h. */
436 validate_flags_qcs (const char *which_command
, qcs_flags
*flags
)
438 if (flags
->cont
&& flags
->silent
)
439 error (_("%s: -c and -s are mutually exclusive"), which_command
);