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