]> Git Repo - binutils.git/blob - gdb/cli/cli-utils.c
Convert tid_range_parser and get_number_or_range to classes
[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 number_or_range_parser::number_or_range_parser (const char *string)
125 {
126   init (string);
127 }
128
129 /* See documentation in cli-utils.h.  */
130
131 void
132 number_or_range_parser::init (const char *string)
133 {
134   m_finished = false;
135   m_cur_tok = string;
136   m_last_retval = 0;
137   m_end_value = 0;
138   m_end_ptr = NULL;
139   m_in_range = false;
140 }
141
142 /* See documentation in cli-utils.h.  */
143
144 int
145 number_or_range_parser::get_number ()
146 {
147   if (m_in_range)
148     {
149       /* All number-parsing has already been done.  Return the next
150          integer value (one greater than the saved previous value).
151          Do not advance the token pointer until the end of range is
152          reached.  */
153
154       if (++m_last_retval == m_end_value)
155         {
156           /* End of range reached; advance token pointer.  */
157           m_cur_tok = m_end_ptr;
158           m_in_range = false;
159         }
160     }
161   else if (*m_cur_tok != '-')
162     {
163       /* Default case: state->m_cur_tok is pointing either to a solo
164          number, or to the first number of a range.  */
165       m_last_retval = get_number_trailer (&m_cur_tok, '-');
166       if (*m_cur_tok == '-')
167         {
168           const char **temp;
169
170           /* This is the start of a range (<number1> - <number2>).
171              Skip the '-', parse and remember the second number,
172              and also remember the end of the final token.  */
173
174           temp = &m_end_ptr;
175           m_end_ptr = skip_spaces_const (m_cur_tok + 1);
176           m_end_value = get_number_const (temp);
177           if (m_end_value < m_last_retval)
178             {
179               error (_("inverted range"));
180             }
181           else if (m_end_value == m_last_retval)
182             {
183               /* Degenerate range (number1 == number2).  Advance the
184                  token pointer so that the range will be treated as a
185                  single number.  */
186               m_cur_tok = m_end_ptr;
187             }
188           else
189             m_in_range = true;
190         }
191     }
192   else
193     error (_("negative value"));
194   m_finished = *m_cur_tok == '\0';
195   return m_last_retval;
196 }
197
198 /* See documentation in cli-utils.h.  */
199
200 void
201 number_or_range_parser::setup_range (int start_value, int end_value,
202                                      const char *end_ptr)
203 {
204   gdb_assert (start_value > 0);
205
206   m_in_range = true;
207   m_end_ptr = end_ptr;
208   m_last_retval = start_value - 1;
209   m_end_value = end_value;
210 }
211
212 /* Accept a number and a string-form list of numbers such as is 
213    accepted by get_number_or_range.  Return TRUE if the number is
214    in the list.
215
216    By definition, an empty list includes all numbers.  This is to 
217    be interpreted as typing a command such as "delete break" with 
218    no arguments.  */
219
220 int
221 number_is_in_list (const char *list, int number)
222 {
223   if (list == NULL || *list == '\0')
224     return 1;
225
226   number_or_range_parser parser (list);
227   while (!parser.finished ())
228     {
229       int gotnum = parser.get_number ();
230
231       if (gotnum == 0)
232         error (_("Args must be numbers or '$' variables."));
233       if (gotnum == number)
234         return 1;
235     }
236   return 0;
237 }
238
239 /* See documentation in cli-utils.h.  */
240
241 char *
242 remove_trailing_whitespace (const char *start, char *s)
243 {
244   while (s > start && isspace (*(s - 1)))
245     --s;
246
247   return s;
248 }
249
250 /* See documentation in cli-utils.h.  */
251
252 char *
253 extract_arg_const (const char **arg)
254 {
255   const char *result;
256
257   if (!*arg)
258     return NULL;
259
260   /* Find the start of the argument.  */
261   *arg = skip_spaces_const (*arg);
262   if (!**arg)
263     return NULL;
264   result = *arg;
265
266   /* Find the end of the argument.  */
267   *arg = skip_to_space_const (*arg + 1);
268
269   if (result == *arg)
270     return NULL;
271
272   return savestring (result, *arg - result);
273 }
274
275 /* See documentation in cli-utils.h.  */
276
277 char *
278 extract_arg (char **arg)
279 {
280   const char *arg_const = *arg;
281   char *result;
282
283   result = extract_arg_const (&arg_const);
284   *arg += arg_const - *arg;
285   return result;
286 }
287
288 /* See documentation in cli-utils.h.  */
289
290 int
291 check_for_argument (char **str, char *arg, int arg_len)
292 {
293   if (strncmp (*str, arg, arg_len) == 0
294       && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
295     {
296       *str += arg_len;
297       return 1;
298     }
299   return 0;
300 }
This page took 0.043594 seconds and 4 git commands to generate.