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