2012-04-27 Sergio Durigan Junior <sergiodj@redhat.com>
[deliverable/binutils-gdb.git] / gdb / cli / cli-utils.c
CommitLineData
e9cafbcc
TT
1/* CLI utilities.
2
0b302171 3 Copyright (c) 2011-2012 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"
22#include "gdb_string.h"
23#include "value.h"
3bd0f5ef 24#include "gdb_assert.h"
e9cafbcc
TT
25
26#include <ctype.h>
27
28/* *PP is a string denoting a number. Get the number of the. Advance
29 *PP after the string and any trailing whitespace.
30
3bd0f5ef
MS
31 Currently the string can either be a number, or "$" followed by the
32 name of a convenience variable, or ("$" or "$$") followed by digits.
e9cafbcc
TT
33
34 TRAILER is a character which can be found after the number; most
35 commonly this is `-'. If you don't want a trailer, use \0. */
36
37static int
38get_number_trailer (char **pp, int trailer)
39{
40 int retval = 0; /* default */
41 char *p = *pp;
42
43 if (*p == '$')
44 {
3bd0f5ef 45 struct value *val = value_from_history_ref (p, &p);
e9cafbcc 46
3bd0f5ef 47 if (val) /* Value history reference */
e9cafbcc 48 {
3bd0f5ef
MS
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."));
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 char *start = ++p;
63 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), &val))
71 retval = (int) val;
72 else
73 {
74 printf_filtered (_("Convenience variable must "
75 "have integer value.\n"));
76 retval = 0;
77 }
e9cafbcc
TT
78 }
79 }
80 else
81 {
82 if (*p == '-')
83 ++p;
84 while (*p >= '0' && *p <= '9')
85 ++p;
86 if (p == *pp)
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 (*pp);
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 retval;
108}
109
110/* See documentation in cli-utils.h. */
111
112int
113get_number (char **pp)
114{
115 return get_number_trailer (pp, '\0');
116}
117
118/* See documentation in cli-utils.h. */
119
197f0a60
TT
120void
121init_number_or_range (struct get_number_or_range_state *state,
122 char *string)
e9cafbcc 123{
197f0a60
TT
124 memset (state, 0, sizeof (*state));
125 state->string = string;
126}
127
128/* See documentation in cli-utils.h. */
e9cafbcc 129
197f0a60
TT
130int
131get_number_or_range (struct get_number_or_range_state *state)
132{
133 if (*state->string != '-')
e9cafbcc 134 {
197f0a60
TT
135 /* Default case: state->string is pointing either to a solo
136 number, or to the first number of a range. */
137 state->last_retval = get_number_trailer (&state->string, '-');
138 if (*state->string == '-')
e9cafbcc
TT
139 {
140 char **temp;
141
142 /* This is the start of a range (<number1> - <number2>).
143 Skip the '-', parse and remember the second number,
144 and also remember the end of the final token. */
145
197f0a60
TT
146 temp = &state->end_ptr;
147 state->end_ptr = skip_spaces (state->string + 1);
148 state->end_value = get_number (temp);
149 if (state->end_value < state->last_retval)
e9cafbcc
TT
150 {
151 error (_("inverted range"));
152 }
197f0a60 153 else if (state->end_value == state->last_retval)
e9cafbcc
TT
154 {
155 /* Degenerate range (number1 == number2). Advance the
156 token pointer so that the range will be treated as a
157 single number. */
197f0a60 158 state->string = state->end_ptr;
e9cafbcc
TT
159 }
160 else
197f0a60 161 state->in_range = 1;
e9cafbcc
TT
162 }
163 }
197f0a60 164 else if (! state->in_range)
e9cafbcc
TT
165 error (_("negative value"));
166 else
167 {
197f0a60 168 /* state->string points to the '-' that betokens a range. All
e9cafbcc
TT
169 number-parsing has already been done. Return the next
170 integer value (one greater than the saved previous value).
197f0a60 171 Do not advance the token pointer until the end of range
e9cafbcc
TT
172 is reached. */
173
197f0a60 174 if (++state->last_retval == state->end_value)
e9cafbcc
TT
175 {
176 /* End of range reached; advance token pointer. */
197f0a60
TT
177 state->string = state->end_ptr;
178 state->in_range = 0;
e9cafbcc
TT
179 }
180 }
197f0a60
TT
181 state->finished = *state->string == '\0';
182 return state->last_retval;
e9cafbcc
TT
183}
184
aea5b279
MS
185/* Accept a number and a string-form list of numbers such as is
186 accepted by get_number_or_range. Return TRUE if the number is
187 in the list.
188
189 By definition, an empty list includes all numbers. This is to
190 be interpreted as typing a command such as "delete break" with
191 no arguments. */
192
193int
194number_is_in_list (char *list, int number)
195{
197f0a60
TT
196 struct get_number_or_range_state state;
197
aea5b279
MS
198 if (list == NULL || *list == '\0')
199 return 1;
200
197f0a60
TT
201 init_number_or_range (&state, list);
202 while (!state.finished)
298f437a 203 {
197f0a60 204 int gotnum = get_number_or_range (&state);
aea5b279 205
298f437a
MS
206 if (gotnum == 0)
207 error (_("Args must be numbers or '$' variables."));
208 if (gotnum == number)
209 return 1;
210 }
aea5b279
MS
211 return 0;
212}
213
e9cafbcc
TT
214/* See documentation in cli-utils.h. */
215
216char *
217skip_spaces (char *chp)
218{
219 if (chp == NULL)
220 return NULL;
221 while (*chp && isspace (*chp))
222 chp++;
223 return chp;
224}
225
55aa24fb
SDJ
226/* A const-correct version of the above. */
227
228const char *
229skip_spaces_const (const char *chp)
230{
231 if (chp == NULL)
232 return NULL;
233 while (*chp && isspace (*chp))
234 chp++;
235 return chp;
236}
237
e9cafbcc
TT
238/* See documentation in cli-utils.h. */
239
240char *
241skip_to_space (char *chp)
242{
243 if (chp == NULL)
244 return NULL;
245 while (*chp && !isspace (*chp))
246 chp++;
247 return chp;
248}
c00f8484
KS
249
250/* See documentation in cli-utils.h. */
251
252char *
253remove_trailing_whitespace (const char *start, char *s)
254{
255 while (s > start && isspace (*(s - 1)))
256 --s;
257
258 return s;
259}
55aa24fb
SDJ
260
261/* See documentation in cli-utils.h. */
262
263char *
264extract_arg (char **arg)
265{
266 char *result, *copy;
267
268 if (!*arg)
269 return NULL;
270
271 /* Find the start of the argument. */
272 *arg = skip_spaces (*arg);
273 if (!**arg)
274 return NULL;
275 result = *arg;
276
277 /* Find the end of the argument. */
278 *arg = skip_to_space (*arg + 1);
279
280 if (result == *arg)
281 return NULL;
282
283 copy = xmalloc (*arg - result + 1);
284 memcpy (copy, result, *arg - result);
285 copy[*arg - result] = '\0';
286
287 return copy;
288}
This page took 0.173711 seconds and 4 git commands to generate.