2011-02-21 Michael Snyder <msnyder@vmware.com>
[platform/upstream/binutils.git] / gdb / cli / cli-utils.c
1 /* CLI utilities.
2
3    Copyright (c) 2011 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 "gdb_string.h"
23 #include "value.h"
24
25 #include <ctype.h>
26
27 /* *PP is a string denoting a number.  Get the number of the.  Advance
28    *PP after the string and any trailing whitespace.
29
30    Currently the string can either be a number or "$" followed by the
31    name of a convenience variable.
32
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.  */
35
36 static int
37 get_number_trailer (char **pp, int trailer)
38 {
39   int retval = 0;       /* default */
40   char *p = *pp;
41
42   if (*p == '$')
43     {
44       /* Make a copy of the name, so we can null-terminate it
45          to pass to lookup_internalvar().  */
46       char *varname;
47       char *start = ++p;
48       LONGEST val;
49
50       while (isalnum (*p) || *p == '_')
51         p++;
52       varname = (char *) alloca (p - start + 1);
53       strncpy (varname, start, p - start);
54       varname[p - start] = '\0';
55       if (get_internalvar_integer (lookup_internalvar (varname), &val))
56         retval = (int) val;
57       else
58         {
59           printf_filtered (_("Convenience variable must "
60                              "have integer value.\n"));
61           retval = 0;
62         }
63     }
64   else
65     {
66       if (*p == '-')
67         ++p;
68       while (*p >= '0' && *p <= '9')
69         ++p;
70       if (p == *pp)
71         /* There is no number here.  (e.g. "cond a == b").  */
72         {
73           /* Skip non-numeric token.  */
74           while (*p && !isspace((int) *p))
75             ++p;
76           /* Return zero, which caller must interpret as error.  */
77           retval = 0;
78         }
79       else
80         retval = atoi (*pp);
81     }
82   if (!(isspace (*p) || *p == '\0' || *p == trailer))
83     {
84       /* Trailing junk: return 0 and let caller print error msg.  */
85       while (!(isspace (*p) || *p == '\0' || *p == trailer))
86         ++p;
87       retval = 0;
88     }
89   p = skip_spaces (p);
90   *pp = p;
91   return retval;
92 }
93
94 /* See documentation in cli-utils.h.  */
95
96 int
97 get_number (char **pp)
98 {
99   return get_number_trailer (pp, '\0');
100 }
101
102 /* See documentation in cli-utils.h.  */
103
104 int
105 get_number_or_range (char **pp)
106 {
107   static int last_retval, end_value;
108   static char *end_ptr;
109   static int in_range = 0;
110
111   if (**pp != '-')
112     {
113       /* Default case: pp is pointing either to a solo number, 
114          or to the first number of a range.  */
115       last_retval = get_number_trailer (pp, '-');
116       if (**pp == '-')
117         {
118           char **temp;
119
120           /* This is the start of a range (<number1> - <number2>).
121              Skip the '-', parse and remember the second number,
122              and also remember the end of the final token.  */
123
124           temp = &end_ptr; 
125           end_ptr = *pp + 1; 
126           while (isspace ((int) *end_ptr))
127             end_ptr++;  /* skip white space */
128           end_value = get_number (temp);
129           if (end_value < last_retval) 
130             {
131               error (_("inverted range"));
132             }
133           else if (end_value == last_retval)
134             {
135               /* Degenerate range (number1 == number2).  Advance the
136                  token pointer so that the range will be treated as a
137                  single number.  */ 
138               *pp = end_ptr;
139             }
140           else
141             in_range = 1;
142         }
143     }
144   else if (! in_range)
145     error (_("negative value"));
146   else
147     {
148       /* pp points to the '-' that betokens a range.  All
149          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 'pp' until the end of range
152          is reached.  */
153
154       if (++last_retval == end_value)
155         {
156           /* End of range reached; advance token pointer.  */
157           *pp = end_ptr;
158           in_range = 0;
159         }
160     }
161   return last_retval;
162 }
163
164 /* Accept a number and a string-form list of numbers such as is 
165    accepted by get_number_or_range.  Return TRUE if the number is
166    in the list.
167
168    By definition, an empty list includes all numbers.  This is to 
169    be interpreted as typing a command such as "delete break" with 
170    no arguments.  */
171
172 int
173 number_is_in_list (char *list, int number)
174 {
175   if (list == NULL || *list == '\0')
176     return 1;
177
178   while (list != NULL && *list != '\0')
179     if (get_number_or_range (&list) == number)
180       return 1;
181
182   return 0;
183 }
184
185 /* See documentation in cli-utils.h.  */
186
187 char *
188 skip_spaces (char *chp)
189 {
190   if (chp == NULL)
191     return NULL;
192   while (*chp && isspace (*chp))
193     chp++;
194   return chp;
195 }
196
197 /* See documentation in cli-utils.h.  */
198
199 char *
200 skip_to_space (char *chp)
201 {
202   if (chp == NULL)
203     return NULL;
204   while (*chp && !isspace (*chp))
205     chp++;
206   return chp;
207 }