]> Git Repo - binutils.git/blob - gdb/cli/cli-utils.c
Per-inferior/Inferior-qualified thread IDs
[binutils.git] / gdb / cli / cli-utils.c
1 /* CLI utilities.
2
3    Copyright (C) 2011-2016 Free Software Foundation, Inc.
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 "value.h"
23
24 #include <ctype.h>
25
26 /* See documentation in cli-utils.h.  */
27
28 int
29 get_number_trailer (const char **pp, int trailer)
30 {
31   int retval = 0;       /* default */
32   const char *p = *pp;
33
34   if (*p == '$')
35     {
36       struct value *val = value_from_history_ref (p, &p);
37
38       if (val)  /* Value history reference */
39         {
40           if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
41             retval = value_as_long (val);
42           else
43             {
44               printf_filtered (_("History value must have integer type.\n"));
45               retval = 0;
46             }
47         }
48       else      /* Convenience variable */
49         {
50           /* Internal variable.  Make a copy of the name, so we can
51              null-terminate it to pass to lookup_internalvar().  */
52           char *varname;
53           const char *start = ++p;
54           LONGEST val;
55
56           while (isalnum (*p) || *p == '_')
57             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))
62             retval = (int) val;
63           else
64             {
65               printf_filtered (_("Convenience variable must "
66                                  "have integer value.\n"));
67               retval = 0;
68             }
69         }
70     }
71   else
72     {
73       if (*p == '-')
74         ++p;
75       while (*p >= '0' && *p <= '9')
76         ++p;
77       if (p == *pp)
78         /* There is no number here.  (e.g. "cond a == b").  */
79         {
80           /* Skip non-numeric token.  */
81           while (*p && !isspace((int) *p))
82             ++p;
83           /* Return zero, which caller must interpret as error.  */
84           retval = 0;
85         }
86       else
87         retval = atoi (*pp);
88     }
89   if (!(isspace (*p) || *p == '\0' || *p == trailer))
90     {
91       /* Trailing junk: return 0 and let caller print error msg.  */
92       while (!(isspace (*p) || *p == '\0' || *p == trailer))
93         ++p;
94       retval = 0;
95     }
96   p = skip_spaces_const (p);
97   *pp = p;
98   return retval;
99 }
100
101 /* See documentation in cli-utils.h.  */
102
103 int
104 get_number_const (const char **pp)
105 {
106   return get_number_trailer (pp, '\0');
107 }
108
109 /* See documentation in cli-utils.h.  */
110
111 int
112 get_number (char **pp)
113 {
114   int result;
115   const char *p = *pp;
116
117   result = get_number_trailer (&p, '\0');
118   *pp = (char *) p;
119   return result;
120 }
121
122 /* See documentation in cli-utils.h.  */
123
124 void
125 init_number_or_range (struct get_number_or_range_state *state,
126                       const char *string)
127 {
128   memset (state, 0, sizeof (*state));
129   state->string = string;
130 }
131
132 /* See documentation in cli-utils.h.  */
133
134 int
135 get_number_or_range (struct get_number_or_range_state *state)
136 {
137   if (*state->string != '-')
138     {
139       /* Default case: state->string is pointing either to a solo
140          number, or to the first number of a range.  */
141       state->last_retval = get_number_trailer (&state->string, '-');
142       if (*state->string == '-')
143         {
144           const char **temp;
145
146           /* This is the start of a range (<number1> - <number2>).
147              Skip the '-', parse and remember the second number,
148              and also remember the end of the final token.  */
149
150           temp = &state->end_ptr; 
151           state->end_ptr = skip_spaces_const (state->string + 1);
152           state->end_value = get_number_const (temp);
153           if (state->end_value < state->last_retval) 
154             {
155               error (_("inverted range"));
156             }
157           else if (state->end_value == state->last_retval)
158             {
159               /* Degenerate range (number1 == number2).  Advance the
160                  token pointer so that the range will be treated as a
161                  single number.  */ 
162               state->string = state->end_ptr;
163             }
164           else
165             state->in_range = 1;
166         }
167     }
168   else if (! state->in_range)
169     error (_("negative value"));
170   else
171     {
172       /* state->string points to the '-' that betokens a range.  All
173          number-parsing has already been done.  Return the next
174          integer value (one greater than the saved previous value).
175          Do not advance the token pointer until the end of range
176          is reached.  */
177
178       if (++state->last_retval == state->end_value)
179         {
180           /* End of range reached; advance token pointer.  */
181           state->string = state->end_ptr;
182           state->in_range = 0;
183         }
184     }
185   state->finished = *state->string == '\0';
186   return state->last_retval;
187 }
188
189 /* Accept a number and a string-form list of numbers such as is 
190    accepted by get_number_or_range.  Return TRUE if the number is
191    in the list.
192
193    By definition, an empty list includes all numbers.  This is to 
194    be interpreted as typing a command such as "delete break" with 
195    no arguments.  */
196
197 int
198 number_is_in_list (const char *list, int number)
199 {
200   struct get_number_or_range_state state;
201
202   if (list == NULL || *list == '\0')
203     return 1;
204
205   init_number_or_range (&state, list);
206   while (!state.finished)
207     {
208       int gotnum = get_number_or_range (&state);
209
210       if (gotnum == 0)
211         error (_("Args must be numbers or '$' variables."));
212       if (gotnum == number)
213         return 1;
214     }
215   return 0;
216 }
217
218 /* See documentation in cli-utils.h.  */
219
220 char *
221 remove_trailing_whitespace (const char *start, char *s)
222 {
223   while (s > start && isspace (*(s - 1)))
224     --s;
225
226   return s;
227 }
228
229 /* See documentation in cli-utils.h.  */
230
231 char *
232 extract_arg_const (const char **arg)
233 {
234   const char *result;
235
236   if (!*arg)
237     return NULL;
238
239   /* Find the start of the argument.  */
240   *arg = skip_spaces_const (*arg);
241   if (!**arg)
242     return NULL;
243   result = *arg;
244
245   /* Find the end of the argument.  */
246   *arg = skip_to_space_const (*arg + 1);
247
248   if (result == *arg)
249     return NULL;
250
251   return savestring (result, *arg - result);
252 }
253
254 /* See documentation in cli-utils.h.  */
255
256 char *
257 extract_arg (char **arg)
258 {
259   const char *arg_const = *arg;
260   char *result;
261
262   result = extract_arg_const (&arg_const);
263   *arg += arg_const - *arg;
264   return result;
265 }
266
267 /* See documentation in cli-utils.h.  */
268
269 int
270 check_for_argument (char **str, char *arg, int arg_len)
271 {
272   if (strncmp (*str, arg, arg_len) == 0
273       && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
274     {
275       *str += arg_len;
276       return 1;
277     }
278   return 0;
279 }
This page took 0.04323 seconds and 4 git commands to generate.