contrib/gdb-7/gdb/linespec.c
static struct symtabs_and_lines
decode_compound (struct linespec_state *self,
		 char **argptr, char *the_real_saved_arg, char *p)
{
  struct symtabs_and_lines values;
  char *p2;
  char *saved_arg2 = *argptr;
  char *temp_end;
  struct symbol *sym;
  char *copy;
  VEC (symbolp) *sym_classes;
  char *saved_arg, *class_name;
  struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);

  /* If the user specified any completer quote characters in the input,
     strip them.  They are superfluous.  */
  saved_arg = alloca (strlen (the_real_saved_arg) + 1);
  {
    char *dst = saved_arg;
    char *src = the_real_saved_arg;
    char *quotes = get_gdb_completer_quote_characters ();
    while (*src != '\0')
      {
	if (strchr (quotes, *src) == NULL)
	  *dst++ = *src;
	++src;
      }
    *dst = '\0';
  }

  /* First check for "global" namespace specification, of the form
     "::foo".  If found, skip over the colons and jump to normal
     symbol processing.  I.e. the whole line specification starts with
     "::" (note the condition that *argptr == p).  */
  if (p[0] == ':' 
      && ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t')))
    saved_arg2 += 2;

  /* Given our example "AAA::inA::fun", we have two cases to consider:

     1) AAA::inA is the name of a class.  In that case, presumably it
        has a method called "fun"; we then look up that method using
        find_method.

     2) AAA::inA isn't the name of a class.  In that case, either the
        user made a typo, AAA::inA is the name of a namespace, or it is
        the name of a minimal symbol.
	In this case we just delegate to decode_variable.

     Thus, our first task is to find everything before the last set of
     double-colons and figure out if it's the name of a class.  So we
     first loop through all of the double-colons.  */

  p2 = p;		/* Save for restart.  */

  /* This is very messy.  Following the example above we have now the
     following pointers:
     p -> "::inA::fun"
     argptr -> "AAA::inA::fun
     saved_arg -> "AAA::inA::fun
     saved_arg2 -> "AAA::inA::fun
     p2 -> "::inA::fun".  */

  /* In the loop below, with these strings, we'll make 2 passes, each
     is marked in comments.  */

  while (1)
    {
      static char *break_characters = " \t(";

      /* Move pointer up to next possible class/namespace token.  */

      p = p2 + 1;	/* Restart with old value +1.  */

      /* PASS1: at this point p2->"::inA::fun", so p->":inA::fun",
	 i.e. if there is a double-colon, p will now point to the
	 second colon.  */
      /* PASS2: p2->"::fun", p->":fun" */

      /* Move pointer ahead to next double-colon.  */
      while (*p
	     && strchr (break_characters, *p) == NULL
	     && strchr (get_gdb_completer_quote_characters (), *p) == NULL)
	{
	  if (current_language->la_language == language_cplus)
	    p += cp_validate_operator (p);

	  if (p[0] == '<')
	    {
	      temp_end = find_template_name_end (p);
	      if (!temp_end)
		error (_("malformed template specification in command"));
	      p = temp_end;
	    }
	  /* Note that, since, at the start of this loop, p would be
	     pointing to the second colon in a double-colon, we only
	     satisfy the condition below if there is another
	     double-colon to the right (after).  I.e. there is another
	     component that can be a class or a namespace.  I.e, if at
	     the beginning of this loop (PASS1), we had
	     p->":inA::fun", we'll trigger this when p has been
	     advanced to point to "::fun".  */
	  /* PASS2: we will not trigger this.  */
	  else if ((p[0] == ':') && (p[1] == ':'))
	    break;	/* Found double-colon.  */
	  else
	    {
	      /* PASS2: We'll keep getting here, until P points to one of the
		 break characters, at which point we exit this loop.  */
	      if (*p)
		{
		  if (p[1] == '('
		      && strncmp (&p[1], CP_ANONYMOUS_NAMESPACE_STR,
				  CP_ANONYMOUS_NAMESPACE_LEN) == 0)
		    p += CP_ANONYMOUS_NAMESPACE_LEN;
		  else if (strchr (break_characters, *p) == NULL)
		    ++p;
		}
	    }
	}

      if (*p != ':')
	break;		/* Out of the while (1).  This would happen
			   for instance if we have looked up
			   unsuccessfully all the components of the
			   string, and p->""(PASS2).  */

      /* We get here if p points to one of the break characters or "" (i.e.,
	 string ended).  */
      /* Save restart for next time around.  */
      p2 = p;
      /* Restore argptr as it was on entry to this function.  */
      *argptr = saved_arg2;
      /* PASS1: at this point p->"::fun" argptr->"AAA::inA::fun",
	 p2->"::fun".  */

      /* All ready for next pass through the loop.  */
    }			/* while (1) */


  /* Start of lookup in the symbol tables.  */

  /* Lookup in the symbol table the substring between argptr and
     p.  Note, this call changes the value of argptr.  */
  /* Before the call, argptr->"AAA::inA::fun",
     p->"", p2->"::fun".  After the call: argptr->"fun", p, p2
     unchanged.  */
  sym_classes = lookup_prefix_sym (argptr, p2, self->file_symtabs,
				   &class_name);
  make_cleanup (VEC_cleanup (symbolp), &sym_classes);
  make_cleanup (xfree, class_name);

  /* If a class has been found, then we're in case 1 above.  So we
     look up "fun" as a method of those classes.  */
  if (!VEC_empty (symbolp, sym_classes))
    {
      /* Arg token is not digits => try it as a function name.
	 Find the next token (everything up to end or next
	 blank).  */
      if (**argptr
	  && strchr (get_gdb_completer_quote_characters (),
		     **argptr) != NULL)
	{
	  p = skip_quoted (*argptr);
	  *argptr = *argptr + 1;
	}
      else
	{
	  /* At this point argptr->"fun".  */
	  char *a;

	  p = *argptr;
	  while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':'
		 && *p != '(')
	    p++;
	  /* At this point p->"".  String ended.  */
	  /* Nope, C++ operators could have spaces in them
	     ("foo::operator <" or "foo::operator delete []").
	     I apologize, this is a bit hacky...  */
	  if (current_language->la_language == language_cplus
	      && *p == ' ' && p - 8 - *argptr + 1 > 0)
	    {
	      /* The above loop has already swallowed "operator".  */
	      p += cp_validate_operator (p - 8) - 8;
	    }

	  /* Keep any important naming information.  */
	  p = keep_name_info (p, 1);
	}

      /* Allocate our own copy of the substring between argptr and
	 p.  */
      copy = (char *) alloca (p - *argptr + 1);
      memcpy (copy, *argptr, p - *argptr);
      copy[p - *argptr] = '\0';
      if (p != *argptr
	  && copy[p - *argptr - 1]
	  && strchr (get_gdb_completer_quote_characters (),
		     copy[p - *argptr - 1]) != NULL)
	copy[p - *argptr - 1] = '\0';

      /* At this point copy->"fun", p->"".  */

      /* No line number may be specified.  */
      *argptr = skip_spaces (p);
      /* At this point arptr->"".  */

      /* Look for copy as a method of sym_class.  */
      /* At this point copy->"fun", sym_class is "AAA:inA",
	 saved_arg->"AAA::inA::fun".  This concludes the scanning of
	 the string for possible components matches.  If we find it
	 here, we return.  If not, and we are at the and of the string,
	 we'll lookup the whole string in the symbol tables.  */

      values = find_method (self, saved_arg, copy, class_name, sym_classes);

      do_cleanups (cleanup);
      return values;
    } /* End if symbol found.  */


  /* We couldn't find a class, so we're in case 2 above.  We check the
     entire name as a symbol instead.  The simplest way to do this is
     to just throw an exception and let our caller fall through to
     decode_variable.  */

  throw_error (NOT_FOUND_ERROR, _("see caller, this text doesn't matter"));
}
/* This handles C++ and Java compound data structures.  P should point
   at the first component separator, i.e. double-colon or period.  As
   an example, on entrance to this function we could have ARGPTR
   pointing to "AAA::inA::fun" and P pointing to "::inA::fun".  */
This handles C++ and Java compound data structures.  P should point
at the first component separator, i.e. double-colon or period.
This handles C ++ and Java compound data structures . P should point at the first component separator i . e . double - colon or period .
static struct symtabs_and_lines
decode_compound (struct linespec_state *self,
		 char **argptr, char *the_real_saved_arg, char *p)
{
  struct symtabs_and_lines values;
  char *p2;
  char *saved_arg2 = *argptr;
  char *temp_end;
  struct symbol *sym;
  char *copy;
  VEC (symbolp) *sym_classes;
  char *saved_arg, *class_name;
  struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
  saved_arg = alloca (strlen (the_real_saved_arg) + 1);
  {
    char *dst = saved_arg;
    char *src = the_real_saved_arg;
    char *quotes = get_gdb_completer_quote_characters ();
    while (*src != '\0')
      {
	if (strchr (quotes, *src) == NULL)
	  *dst++ = *src;
	++src;
      }
    *dst = '\0';
  }
  if (p[0] == ':' 
      && ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t')))
    saved_arg2 += 2;
  p2 = p;		
  while (1)
    {
      static char *break_characters = " \t(";
      p = p2 + 1;	
      while (*p
	     && strchr (break_characters, *p) == NULL
	     && strchr (get_gdb_completer_quote_characters (), *p) == NULL)
	{
	  if (current_language->la_language == language_cplus)
	    p += cp_validate_operator (p);
	  if (p[0] == '<')
	    {
	      temp_end = find_template_name_end (p);
	      if (!temp_end)
		error (_("malformed template specification in command"));
	      p = temp_end;
	    }
	  else if ((p[0] == ':') && (p[1] == ':'))
	    break;	
	  else
	    {
	      if (*p)
		{
		  if (p[1] == '('
		      && strncmp (&p[1], CP_ANONYMOUS_NAMESPACE_STR,
				  CP_ANONYMOUS_NAMESPACE_LEN) == 0)
		    p += CP_ANONYMOUS_NAMESPACE_LEN;
		  else if (strchr (break_characters, *p) == NULL)
		    ++p;
		}
	    }
	}
      if (*p != ':')
	break;		
      p2 = p;
      *argptr = saved_arg2;
    }			
  sym_classes = lookup_prefix_sym (argptr, p2, self->file_symtabs,
				   &class_name);
  make_cleanup (VEC_cleanup (symbolp), &sym_classes);
  make_cleanup (xfree, class_name);
  if (!VEC_empty (symbolp, sym_classes))
    {
      if (**argptr
	  && strchr (get_gdb_completer_quote_characters (),
		     **argptr) != NULL)
	{
	  p = skip_quoted (*argptr);
	  *argptr = *argptr + 1;
	}
      else
	{
	  char *a;
	  p = *argptr;
	  while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':'
		 && *p != '(')
	    p++;
	  if (current_language->la_language == language_cplus
	      && *p == ' ' && p - 8 - *argptr + 1 > 0)
	    {
	      p += cp_validate_operator (p - 8) - 8;
	    }
	  p = keep_name_info (p, 1);
	}
      copy = (char *) alloca (p - *argptr + 1);
      memcpy (copy, *argptr, p - *argptr);
      copy[p - *argptr] = '\0';
      if (p != *argptr
	  && copy[p - *argptr - 1]
	  && strchr (get_gdb_completer_quote_characters (),
		     copy[p - *argptr - 1]) != NULL)
	copy[p - *argptr - 1] = '\0';
      *argptr = skip_spaces (p);
      values = find_method (self, saved_arg, copy, class_name, sym_classes);
      do_cleanups (cleanup);
      return values;
    } 
  throw_error (NOT_FOUND_ERROR, _("see caller, this text doesn't matter"));
}
static struct symtabs_and_lines decode_compound ( struct linespec_state * self , char * * argptr , char * the_real_saved_arg , char * p ) { struct symtabs_and_lines values ; char * p2 ; char * saved_arg2 = * argptr ; char * temp_end ; struct symbol * sym ; char * copy ; VEC ( symbolp ) * sym_classes ; char * saved_arg , * class_name ; struct cleanup * cleanup = make_cleanup ( null_cleanup , NULL ) ; saved_arg = alloca ( strlen ( the_real_saved_arg ) + 1 ) ; { char * dst = saved_arg ; char * src = the_real_saved_arg ; char * quotes = get_gdb_completer_quote_characters ( ) ; while ( * src != ' \0 ' ) { if ( strchr ( quotes , * src ) == NULL ) * dst ++ = * src ; ++ src ; } * dst = ' \0 ' ; } if ( p [ 0 ] == ' ' && ( ( * argptr == p ) || ( p [ -1 ] == ' ' ) || ( p [ -1 ] == ' \t ' ) ) ) saved_arg2 += 2 ; p2 = p ; while ( 1 ) { static char * break_characters = " \t " ; p = p2 + 1 ; while ( * p && strchr ( break_characters , * p ) == NULL && strchr ( get_gdb_completer_quote_characters ( ) , * p ) == NULL ) { if ( current_language -> la_language == language_cplus ) p += cp_validate_operator ( p ) ; if ( p [ 0 ] == ' ' ) { temp_end = find_template_name_end ( p ) ; if ( ! temp_end ) error ( _ ( " " ) ) ; p = temp_end ; } else if ( ( p [ 0 ] == ' ' ) && ( p [ 1 ] == ' ' ) ) break ; else { if ( * p ) { if ( p [ 1 ] == ' ' && strncmp ( & p [ 1 ] , CP_ANONYMOUS_NAMESPACE_STR , CP_ANONYMOUS_NAMESPACE_LEN ) == 0 ) p += CP_ANONYMOUS_NAMESPACE_LEN ; else if ( strchr ( break_characters , * p ) == NULL ) ++ p ; } } } if ( * p != ' ' ) break ; p2 = p ; * argptr = saved_arg2 ; } sym_classes = lookup_prefix_sym ( argptr , p2 , self -> file_symtabs , & class_name ) ; make_cleanup ( VEC_cleanup ( symbolp ) , & sym_classes ) ; make_cleanup ( xfree , class_name ) ; if ( ! VEC_empty ( symbolp , sym_classes ) ) { if ( * * argptr && strchr ( get_gdb_completer_quote_characters ( ) , * * argptr ) != NULL ) { p = skip_quoted ( * argptr ) ; * argptr = * argptr + 1 ; } else { char * a ; p = * argptr ; while ( * p && * p != ' ' && * p != ' \t ' && * p != ' ' && * p != ' ' && * p != ' ' ) p ++ ; if ( current_language -> la_language == language_cplus && * p == ' ' && p - 8 - * argptr + 1 > 0 ) { p += cp_validate_operator ( p - 8 ) - 8 ; } p = keep_name_info ( p , 1 ) ; } copy = ( char * ) alloca ( p - * argptr + 1 ) ; memcpy ( copy , * argptr , p - * argptr ) ; copy [ p - * argptr ] = ' \0 ' ; if ( p != * argptr && copy [ p - * argptr - 1 ] && strchr ( get_gdb_completer_quote_characters ( ) , copy [ p - * argptr - 1 ] ) != NULL ) copy [ p - * argptr - 1 ] = ' \0 ' ; * argptr = skip_spaces ( p ) ; values = find_method ( self , saved_arg , copy , class_name , sym_classes ) ; do_cleanups ( cleanup ) ; return values ; } throw_error ( NOT_FOUND_ERROR , _ ( " " ) ) ; }
This handles C++ and Java compound data structures.
This handles C ++ and Java compound data structures .
/* If the user specified any completer quote characters in the input,
     strip them.  They are superfluous.  */ /* First check for "global" namespace specification, of the form
     "::foo".  If found, skip over the colons and jump to normal
     symbol processing.  I.e. the whole line specification starts with
     "::" (note the condition that *argptr == p).  */ /* Given our example "AAA::inA::fun", we have two cases to consider:

     1) AAA::inA is the name of a class.  In that case, presumably it
        has a method called "fun"; we then look up that method using
        find_method.

     2) AAA::inA isn't the name of a class.  In that case, either the
        user made a typo, AAA::inA is the name of a namespace, or it is
        the name of a minimal symbol.
	In this case we just delegate to decode_variable.

     Thus, our first task is to find everything before the last set of
     double-colons and figure out if it's the name of a class.  So we
     first loop through all of the double-colons.  */ /* Save for restart.  */ /* This is very messy.  Following the example above we have now the
     following pointers:
     p -> "::inA::fun"
     argptr -> "AAA::inA::fun
     saved_arg -> "AAA::inA::fun
     saved_arg2 -> "AAA::inA::fun
     p2 -> "::inA::fun".  */ /* In the loop below, with these strings, we'll make 2 passes, each
     is marked in comments.  */ /* Move pointer up to next possible class/namespace token.  */ /* Restart with old value +1.  */ /* PASS1: at this point p2->"::inA::fun", so p->":inA::fun",
	 i.e. if there is a double-colon, p will now point to the
	 second colon.  */ /* PASS2: p2->"::fun", p->":fun" */ /* Move pointer ahead to next double-colon.  */ /* Note that, since, at the start of this loop, p would be
	     pointing to the second colon in a double-colon, we only
	     satisfy the condition below if there is another
	     double-colon to the right (after).  I.e. there is another
	     component that can be a class or a namespace.  I.e, if at
	     the beginning of this loop (PASS1), we had
	     p->":inA::fun", we'll trigger this when p has been
	     advanced to point to "::fun".  */ /* PASS2: we will not trigger this.  */ /* Found double-colon.  */ /* PASS2: We'll keep getting here, until P points to one of the
		 break characters, at which point we exit this loop.  */ /* Out of the while (1).  This would happen
			   for instance if we have looked up
			   unsuccessfully all the components of the
			   string, and p->""(PASS2).  */ /* We get here if p points to one of the break characters or "" (i.e.,
	 string ended).  */ /* Save restart for next time around.  */ /* Restore argptr as it was on entry to this function.  */ /* PASS1: at this point p->"::fun" argptr->"AAA::inA::fun",
	 p2->"::fun".  */ /* All ready for next pass through the loop.  */ /* while (1) */ /* Start of lookup in the symbol tables.  */ /* Lookup in the symbol table the substring between argptr and
     p.  Note, this call changes the value of argptr.  */ /* Before the call, argptr->"AAA::inA::fun",
     p->"", p2->"::fun".  After the call: argptr->"fun", p, p2
     unchanged.  */ /* If a class has been found, then we're in case 1 above.  So we
     look up "fun" as a method of those classes.  */ /* Arg token is not digits => try it as a function name.
	 Find the next token (everything up to end or next
	 blank).  */ /* At this point argptr->"fun".  */ /* At this point p->"".  String ended.  */ /* Nope, C++ operators could have spaces in them
	     ("foo::operator <" or "foo::operator delete []").
	     I apologize, this is a bit hacky...  */ /* The above loop has already swallowed "operator".  */ /* Keep any important naming information.  */ /* Allocate our own copy of the substring between argptr and
	 p.  */ /* At this point copy->"fun", p->"".  */ /* No line number may be specified.  */ /* At this point arptr->"".  */ /* Look for copy as a method of sym_class.  */ /* At this point copy->"fun", sym_class is "AAA:inA",
	 saved_arg->"AAA::inA::fun".  This concludes the scanning of
	 the string for possible components matches.  If we find it
	 here, we return.  If not, and we are at the and of the string,
	 we'll lookup the whole string in the symbol tables.  */ /* End if symbol found.  */ /* We couldn't find a class, so we're in case 2 above.  We check the
     entire name as a symbol instead.  The simplest way to do this is
     to just throw an exception and let our caller fall through to
     decode_variable.  */