3 Copyright (C) 2011-2016 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_number_trailer (const char **pp
, int trailer
)
31 int retval
= 0; /* default */
36 struct value
*val
= value_from_history_ref (p
, &p
);
38 if (val
) /* Value history reference */
40 if (TYPE_CODE (value_type (val
)) == TYPE_CODE_INT
)
41 retval
= value_as_long (val
);
44 printf_filtered (_("History value must have integer type.\n"));
48 else /* Convenience variable */
50 /* Internal variable. Make a copy of the name, so we can
51 null-terminate it to pass to lookup_internalvar(). */
53 const char *start
= ++p
;
56 while (isalnum (*p
) || *p
== '_')
58 varname
= (char *) alloca (p
- start
+ 1);
59 strncpy (varname
, start
, p
- start
);
60 varname
[p
- start
] = '\0';
61 if (get_internalvar_integer (lookup_internalvar (varname
), &val
))
65 printf_filtered (_("Convenience variable must "
66 "have integer value.\n"));
75 while (*p
>= '0' && *p
<= '9')
78 /* There is no number here. (e.g. "cond a == b"). */
80 /* Skip non-numeric token. */
81 while (*p
&& !isspace((int) *p
))
83 /* Return zero, which caller must interpret as error. */
89 if (!(isspace (*p
) || *p
== '\0' || *p
== trailer
))
91 /* Trailing junk: return 0 and let caller print error msg. */
92 while (!(isspace (*p
) || *p
== '\0' || *p
== trailer
))
96 p
= skip_spaces_const (p
);
101 /* See documentation in cli-utils.h. */
104 get_number_const (const char **pp
)
106 return get_number_trailer (pp
, '\0');
109 /* See documentation in cli-utils.h. */
112 get_number (char **pp
)
117 result
= get_number_trailer (&p
, '\0');
122 /* See documentation in cli-utils.h. */
125 init_number_or_range (struct get_number_or_range_state
*state
,
128 memset (state
, 0, sizeof (*state
));
129 state
->string
= string
;
132 /* See documentation in cli-utils.h. */
135 get_number_or_range (struct get_number_or_range_state
*state
)
139 /* All number-parsing has already been done. Return the next
140 integer value (one greater than the saved previous value).
141 Do not advance the token pointer until the end of range is
144 if (++state
->last_retval
== state
->end_value
)
146 /* End of range reached; advance token pointer. */
147 state
->string
= state
->end_ptr
;
151 else if (*state
->string
!= '-')
153 /* Default case: state->string is pointing either to a solo
154 number, or to the first number of a range. */
155 state
->last_retval
= get_number_trailer (&state
->string
, '-');
156 if (*state
->string
== '-')
160 /* This is the start of a range (<number1> - <number2>).
161 Skip the '-', parse and remember the second number,
162 and also remember the end of the final token. */
164 temp
= &state
->end_ptr
;
165 state
->end_ptr
= skip_spaces_const (state
->string
+ 1);
166 state
->end_value
= get_number_const (temp
);
167 if (state
->end_value
< state
->last_retval
)
169 error (_("inverted range"));
171 else if (state
->end_value
== state
->last_retval
)
173 /* Degenerate range (number1 == number2). Advance the
174 token pointer so that the range will be treated as a
176 state
->string
= state
->end_ptr
;
183 error (_("negative value"));
184 state
->finished
= *state
->string
== '\0';
185 return state
->last_retval
;
188 /* See documentation in cli-utils.h. */
191 number_range_setup_range (struct get_number_or_range_state
*state
,
192 int start_value
, int end_value
, const char *end_ptr
)
194 gdb_assert (start_value
> 0);
197 state
->end_ptr
= end_ptr
;
198 state
->last_retval
= start_value
- 1;
199 state
->end_value
= end_value
;
202 /* Accept a number and a string-form list of numbers such as is
203 accepted by get_number_or_range. Return TRUE if the number is
206 By definition, an empty list includes all numbers. This is to
207 be interpreted as typing a command such as "delete break" with
211 number_is_in_list (const char *list
, int number
)
213 struct get_number_or_range_state state
;
215 if (list
== NULL
|| *list
== '\0')
218 init_number_or_range (&state
, list
);
219 while (!state
.finished
)
221 int gotnum
= get_number_or_range (&state
);
224 error (_("Args must be numbers or '$' variables."));
225 if (gotnum
== number
)
231 /* See documentation in cli-utils.h. */
234 remove_trailing_whitespace (const char *start
, char *s
)
236 while (s
> start
&& isspace (*(s
- 1)))
242 /* See documentation in cli-utils.h. */
245 extract_arg_const (const char **arg
)
252 /* Find the start of the argument. */
253 *arg
= skip_spaces_const (*arg
);
258 /* Find the end of the argument. */
259 *arg
= skip_to_space_const (*arg
+ 1);
264 return savestring (result
, *arg
- result
);
267 /* See documentation in cli-utils.h. */
270 extract_arg (char **arg
)
272 const char *arg_const
= *arg
;
275 result
= extract_arg_const (&arg_const
);
276 *arg
+= arg_const
- *arg
;
280 /* See documentation in cli-utils.h. */
283 check_for_argument (char **str
, char *arg
, int arg_len
)
285 if (strncmp (*str
, arg
, arg_len
) == 0
286 && ((*str
)[arg_len
] == '\0' || isspace ((*str
)[arg_len
])))