3 Copyright (C) 2011-2014 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"
27 /* *PP is a string denoting a number. Get the number of the. Advance
28 *PP after the string and any trailing whitespace.
30 Currently the string can either be a number, or "$" followed by the
31 name of a convenience variable, or ("$" or "$$") followed by digits.
33 TRAILER is a character which can be found after the number; most
34 commonly this is `-'. If you don't want a trailer, use \0. */
37 get_number_trailer (const char **pp
, int trailer
)
39 int retval
= 0; /* default */
44 struct value
*val
= value_from_history_ref (p
, &p
);
46 if (val
) /* Value history reference */
48 if (TYPE_CODE (value_type (val
)) == TYPE_CODE_INT
)
49 retval
= value_as_long (val
);
52 printf_filtered (_("History value must have integer type.\n"));
56 else /* Convenience variable */
58 /* Internal variable. Make a copy of the name, so we can
59 null-terminate it to pass to lookup_internalvar(). */
61 const char *start
= ++p
;
64 while (isalnum (*p
) || *p
== '_')
66 varname
= (char *) alloca (p
- start
+ 1);
67 strncpy (varname
, start
, p
- start
);
68 varname
[p
- start
] = '\0';
69 if (get_internalvar_integer (lookup_internalvar (varname
), &val
))
73 printf_filtered (_("Convenience variable must "
74 "have integer value.\n"));
83 while (*p
>= '0' && *p
<= '9')
86 /* There is no number here. (e.g. "cond a == b"). */
88 /* Skip non-numeric token. */
89 while (*p
&& !isspace((int) *p
))
91 /* Return zero, which caller must interpret as error. */
97 if (!(isspace (*p
) || *p
== '\0' || *p
== trailer
))
99 /* Trailing junk: return 0 and let caller print error msg. */
100 while (!(isspace (*p
) || *p
== '\0' || *p
== trailer
))
104 p
= skip_spaces_const (p
);
109 /* See documentation in cli-utils.h. */
112 get_number_const (const char **pp
)
114 return get_number_trailer (pp
, '\0');
117 /* See documentation in cli-utils.h. */
120 get_number (char **pp
)
125 result
= get_number_trailer (&p
, '\0');
130 /* See documentation in cli-utils.h. */
133 init_number_or_range (struct get_number_or_range_state
*state
,
136 memset (state
, 0, sizeof (*state
));
137 state
->string
= string
;
140 /* See documentation in cli-utils.h. */
143 get_number_or_range (struct get_number_or_range_state
*state
)
145 if (*state
->string
!= '-')
147 /* Default case: state->string is pointing either to a solo
148 number, or to the first number of a range. */
149 state
->last_retval
= get_number_trailer (&state
->string
, '-');
150 if (*state
->string
== '-')
154 /* This is the start of a range (<number1> - <number2>).
155 Skip the '-', parse and remember the second number,
156 and also remember the end of the final token. */
158 temp
= &state
->end_ptr
;
159 state
->end_ptr
= skip_spaces_const (state
->string
+ 1);
160 state
->end_value
= get_number_const (temp
);
161 if (state
->end_value
< state
->last_retval
)
163 error (_("inverted range"));
165 else if (state
->end_value
== state
->last_retval
)
167 /* Degenerate range (number1 == number2). Advance the
168 token pointer so that the range will be treated as a
170 state
->string
= state
->end_ptr
;
176 else if (! state
->in_range
)
177 error (_("negative value"));
180 /* state->string points to the '-' that betokens a range. All
181 number-parsing has already been done. Return the next
182 integer value (one greater than the saved previous value).
183 Do not advance the token pointer until the end of range
186 if (++state
->last_retval
== state
->end_value
)
188 /* End of range reached; advance token pointer. */
189 state
->string
= state
->end_ptr
;
193 state
->finished
= *state
->string
== '\0';
194 return state
->last_retval
;
197 /* Accept a number and a string-form list of numbers such as is
198 accepted by get_number_or_range. Return TRUE if the number is
201 By definition, an empty list includes all numbers. This is to
202 be interpreted as typing a command such as "delete break" with
206 number_is_in_list (const char *list
, int number
)
208 struct get_number_or_range_state state
;
210 if (list
== NULL
|| *list
== '\0')
213 init_number_or_range (&state
, list
);
214 while (!state
.finished
)
216 int gotnum
= get_number_or_range (&state
);
219 error (_("Args must be numbers or '$' variables."));
220 if (gotnum
== number
)
226 /* See documentation in cli-utils.h. */
229 skip_spaces (char *chp
)
233 while (*chp
&& isspace (*chp
))
238 /* A const-correct version of the above. */
241 skip_spaces_const (const char *chp
)
245 while (*chp
&& isspace (*chp
))
250 /* See documentation in cli-utils.h. */
253 skip_to_space_const (const char *chp
)
257 while (*chp
&& !isspace (*chp
))
262 /* See documentation in cli-utils.h. */
265 remove_trailing_whitespace (const char *start
, char *s
)
267 while (s
> start
&& isspace (*(s
- 1)))
273 /* See documentation in cli-utils.h. */
276 extract_arg_const (const char **arg
)
283 /* Find the start of the argument. */
284 *arg
= skip_spaces_const (*arg
);
289 /* Find the end of the argument. */
290 *arg
= skip_to_space_const (*arg
+ 1);
295 return savestring (result
, *arg
- result
);
298 /* See documentation in cli-utils.h. */
301 extract_arg (char **arg
)
303 const char *arg_const
= *arg
;
306 result
= extract_arg_const (&arg_const
);
307 *arg
+= arg_const
- *arg
;
311 /* See documentation in cli-utils.h. */
314 check_for_argument (char **str
, char *arg
, int arg_len
)
316 if (strncmp (*str
, arg
, arg_len
) == 0
317 && ((*str
)[arg_len
] == '\0' || isspace ((*str
)[arg_len
])))