GDB (API)
/home/stan/gdb/src/gdb/cli/cli-utils.c
Go to the documentation of this file.
00001 /* CLI utilities.
00002 
00003    Copyright (C) 2011-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "cli/cli-utils.h"
00022 #include "gdb_string.h"
00023 #include "value.h"
00024 #include "gdb_assert.h"
00025 
00026 #include <ctype.h>
00027 
00028 /* *PP is a string denoting a number.  Get the number of the.  Advance
00029    *PP after the string and any trailing whitespace.
00030 
00031    Currently the string can either be a number, or "$" followed by the
00032    name of a convenience variable, or ("$" or "$$") followed by digits.
00033 
00034    TRAILER is a character which can be found after the number; most
00035    commonly this is `-'.  If you don't want a trailer, use \0.  */
00036 
00037 static int
00038 get_number_trailer (char **pp, int trailer)
00039 {
00040   int retval = 0;       /* default */
00041   char *p = *pp;
00042 
00043   if (*p == '$')
00044     {
00045       struct value *val = value_from_history_ref (p, &p);
00046 
00047       if (val)  /* Value history reference */
00048         {
00049           if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
00050             retval = value_as_long (val);
00051           else
00052             {
00053               printf_filtered (_("History value must have integer type."));
00054               retval = 0;
00055             }
00056         }
00057       else      /* Convenience variable */
00058         {
00059           /* Internal variable.  Make a copy of the name, so we can
00060              null-terminate it to pass to lookup_internalvar().  */
00061           char *varname;
00062           char *start = ++p;
00063           LONGEST val;
00064 
00065           while (isalnum (*p) || *p == '_')
00066             p++;
00067           varname = (char *) alloca (p - start + 1);
00068           strncpy (varname, start, p - start);
00069           varname[p - start] = '\0';
00070           if (get_internalvar_integer (lookup_internalvar (varname), &val))
00071             retval = (int) val;
00072           else
00073             {
00074               printf_filtered (_("Convenience variable must "
00075                                  "have integer value.\n"));
00076               retval = 0;
00077             }
00078         }
00079     }
00080   else
00081     {
00082       if (*p == '-')
00083         ++p;
00084       while (*p >= '0' && *p <= '9')
00085         ++p;
00086       if (p == *pp)
00087         /* There is no number here.  (e.g. "cond a == b").  */
00088         {
00089           /* Skip non-numeric token.  */
00090           while (*p && !isspace((int) *p))
00091             ++p;
00092           /* Return zero, which caller must interpret as error.  */
00093           retval = 0;
00094         }
00095       else
00096         retval = atoi (*pp);
00097     }
00098   if (!(isspace (*p) || *p == '\0' || *p == trailer))
00099     {
00100       /* Trailing junk: return 0 and let caller print error msg.  */
00101       while (!(isspace (*p) || *p == '\0' || *p == trailer))
00102         ++p;
00103       retval = 0;
00104     }
00105   p = skip_spaces (p);
00106   *pp = p;
00107   return retval;
00108 }
00109 
00110 /* See documentation in cli-utils.h.  */
00111 
00112 int
00113 get_number (char **pp)
00114 {
00115   return get_number_trailer (pp, '\0');
00116 }
00117 
00118 /* See documentation in cli-utils.h.  */
00119 
00120 void
00121 init_number_or_range (struct get_number_or_range_state *state,
00122                       char *string)
00123 {
00124   memset (state, 0, sizeof (*state));
00125   state->string = string;
00126 }
00127 
00128 /* See documentation in cli-utils.h.  */
00129 
00130 int
00131 get_number_or_range (struct get_number_or_range_state *state)
00132 {
00133   if (*state->string != '-')
00134     {
00135       /* Default case: state->string is pointing either to a solo
00136          number, or to the first number of a range.  */
00137       state->last_retval = get_number_trailer (&state->string, '-');
00138       if (*state->string == '-')
00139         {
00140           char **temp;
00141 
00142           /* This is the start of a range (<number1> - <number2>).
00143              Skip the '-', parse and remember the second number,
00144              and also remember the end of the final token.  */
00145 
00146           temp = &state->end_ptr; 
00147           state->end_ptr = skip_spaces (state->string + 1);
00148           state->end_value = get_number (temp);
00149           if (state->end_value < state->last_retval) 
00150             {
00151               error (_("inverted range"));
00152             }
00153           else if (state->end_value == state->last_retval)
00154             {
00155               /* Degenerate range (number1 == number2).  Advance the
00156                  token pointer so that the range will be treated as a
00157                  single number.  */ 
00158               state->string = state->end_ptr;
00159             }
00160           else
00161             state->in_range = 1;
00162         }
00163     }
00164   else if (! state->in_range)
00165     error (_("negative value"));
00166   else
00167     {
00168       /* state->string points to the '-' that betokens a range.  All
00169          number-parsing has already been done.  Return the next
00170          integer value (one greater than the saved previous value).
00171          Do not advance the token pointer until the end of range
00172          is reached.  */
00173 
00174       if (++state->last_retval == state->end_value)
00175         {
00176           /* End of range reached; advance token pointer.  */
00177           state->string = state->end_ptr;
00178           state->in_range = 0;
00179         }
00180     }
00181   state->finished = *state->string == '\0';
00182   return state->last_retval;
00183 }
00184 
00185 /* Accept a number and a string-form list of numbers such as is 
00186    accepted by get_number_or_range.  Return TRUE if the number is
00187    in the list.
00188 
00189    By definition, an empty list includes all numbers.  This is to 
00190    be interpreted as typing a command such as "delete break" with 
00191    no arguments.  */
00192 
00193 int
00194 number_is_in_list (char *list, int number)
00195 {
00196   struct get_number_or_range_state state;
00197 
00198   if (list == NULL || *list == '\0')
00199     return 1;
00200 
00201   init_number_or_range (&state, list);
00202   while (!state.finished)
00203     {
00204       int gotnum = get_number_or_range (&state);
00205 
00206       if (gotnum == 0)
00207         error (_("Args must be numbers or '$' variables."));
00208       if (gotnum == number)
00209         return 1;
00210     }
00211   return 0;
00212 }
00213 
00214 /* See documentation in cli-utils.h.  */
00215 
00216 char *
00217 skip_spaces (char *chp)
00218 {
00219   if (chp == NULL)
00220     return NULL;
00221   while (*chp && isspace (*chp))
00222     chp++;
00223   return chp;
00224 }
00225 
00226 /* A const-correct version of the above.  */
00227 
00228 const char *
00229 skip_spaces_const (const char *chp)
00230 {
00231   if (chp == NULL)
00232     return NULL;
00233   while (*chp && isspace (*chp))
00234     chp++;
00235   return chp;
00236 }
00237 
00238 /* See documentation in cli-utils.h.  */
00239 
00240 const char *
00241 skip_to_space_const (const char *chp)
00242 {
00243   if (chp == NULL)
00244     return NULL;
00245   while (*chp && !isspace (*chp))
00246     chp++;
00247   return chp;
00248 }
00249 
00250 /* See documentation in cli-utils.h.  */
00251 
00252 char *
00253 remove_trailing_whitespace (const char *start, char *s)
00254 {
00255   while (s > start && isspace (*(s - 1)))
00256     --s;
00257 
00258   return s;
00259 }
00260 
00261 /* See documentation in cli-utils.h.  */
00262 
00263 char *
00264 extract_arg (char **arg)
00265 {
00266   char *result, *copy;
00267 
00268   if (!*arg)
00269     return NULL;
00270 
00271   /* Find the start of the argument.  */
00272   *arg = skip_spaces (*arg);
00273   if (!**arg)
00274     return NULL;
00275   result = *arg;
00276 
00277   /* Find the end of the argument.  */
00278   *arg = skip_to_space (*arg + 1);
00279 
00280   if (result == *arg)
00281     return NULL;
00282 
00283   copy = xmalloc (*arg - result + 1);
00284   memcpy (copy, result, *arg - result);
00285   copy[*arg - result] = '\0';
00286 
00287   return copy;
00288 }
00289 
00290 /* See documentation in cli-utils.h.  */
00291 
00292 int
00293 check_for_argument (char **str, char *arg, int arg_len)
00294 {
00295   if (strncmp (*str, arg, arg_len) == 0
00296       && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len])))
00297     {
00298       *str += arg_len;
00299       return 1;
00300     }
00301   return 0;
00302 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines