This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rfa] linespec.c, part 5


[ Just what is it that causes my fingers to confuse C-cs and C-cC-s at
the start of typing a message, even though my fingers never confuse
them at the end of typing a message?  Sigh... ]

The next part: decode_compound, to handle C++ and Java compound data
structures.  Some notes:

* The function that this creates, decode_compound, is quite long.
  Later patches in this series will break it down into smaller chunks;
  they will come after I've got decode_line_1 itself down to a nice
  size.

* To get this to compile without warnings, I changed the declaration
  of cplusplus_error to note that it doesn't return.

* While preparing this patch, I noticed that the variable
  gdb_completer_quote_characters is declared but not used; I got rid
  of it.

* Since decode_line_1 returns the value of decode_compound, there's no
  need to check whether or not decode_compound modifies the arguments
  that it's been passed: later code in decode_line_1 can never be
  effected by such modifications.

David Carlton
carlton@math.stanford.edu

2002-11-15  David Carlton  <carlton@math.stanford.edu>

	* linespec.c (decode_compound): New function.
	(decode_line_1): Move code into decode_compound.

--- linespec.c-4	Tue Nov 12 14:07:59 2002
+++ linespec.c		Tue Nov 12 15:40:10 2002
@@ -48,7 +48,15 @@ static struct symtabs_and_lines decode_i
 
 static char *locate_first_half (char **argptr, int *is_quote_enclosed);
 
-static void cplusplus_error (const char *name, const char *fmt, ...) ATTR_FORMAT (printf, 2, 3);
+static struct symtabs_and_lines decode_compound (char **argptr,
+						 int funfirstline,
+						 char ***canonical,
+						 char *saved_arg,
+						 char *p);
+
+static NORETURN void cplusplus_error (const char *name,
+				      const char *fmt, ...)
+     ATTR_NORETURN ATTR_FORMAT (printf, 2, 3);
 
 static int total_number_of_methods (struct type *type);
 
@@ -80,7 +88,7 @@ symtabs_and_lines minsym_found (int funf
    single quoted demangled C++ symbols as part of the completion
    error.  */
 
-static void
+static NORETURN void
 cplusplus_error (const char *name, const char *fmt, ...)
 {
   struct ui_file *tmp_stream;
@@ -532,10 +540,7 @@ decode_line_1 (char **argptr, int funfir
   struct symtabs_and_lines values;
   struct symtab_and_line val;
   register char *p, *p1;
-  char *q, *p2;
-#if 0
-  char *q1;
-#endif
+  char *q;
   register struct symtab *s = NULL;
 
   register struct symbol *sym;
@@ -544,8 +549,6 @@ decode_line_1 (char **argptr, int funfir
 
   register struct minimal_symbol *msymbol;
   char *copy;
-  struct symbol *sym_class;
-  int i1;
   /* This is NULL if there are no parens in *ARGPTR, or a pointer to
      the closing parenthesis if there are parens.  */
   char *paren_pointer;
@@ -554,10 +557,7 @@ decode_line_1 (char **argptr, int funfir
   int is_quoted;
   /* Is part of *ARGPTR is enclosed in double quotes?  */
   int is_quote_enclosed;
-  struct symbol **sym_arr;
-  struct type *t;
   char *saved_arg = *argptr;
-  extern char *gdb_completer_quote_characters;
 
   init_sal (&val);		/* initialize to zeroes */
 
@@ -589,237 +589,13 @@ decode_line_1 (char **argptr, int funfir
 
   if ((p[0] == ':' || p[0] == '.') && paren_pointer == NULL)
     {
-      /*  C++ */
-      /*  ... or Java */
       if (is_quoted)
 	*argptr = *argptr + 1;
       if (p[0] == '.' || p[1] == ':')
-	{
-	  char *saved_arg2 = *argptr;
-	  char *temp_end;
-	  /* First check for "global" namespace specification,
-	     of the form "::foo". If found, skip over the colons
-	     and jump to normal symbol processing */
-	  if (p[0] == ':' 
-	      && ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t')))
-	    saved_arg2 += 2;
-
-	  /* We have what looks like a class or namespace
-	     scope specification (A::B), possibly with many
-	     levels of namespaces or classes (A::B::C::D).
-
-	     Some versions of the HP ANSI C++ compiler (as also possibly
-	     other compilers) generate class/function/member names with
-	     embedded double-colons if they are inside namespaces. To
-	     handle this, we loop a few times, considering larger and
-	     larger prefixes of the string as though they were single
-	     symbols.  So, if the initially supplied string is
-	     A::B::C::D::foo, we have to look up "A", then "A::B",
-	     then "A::B::C", then "A::B::C::D", and finally
-	     "A::B::C::D::foo" as single, monolithic symbols, because
-	     A, B, C or D may be namespaces.
-
-	     Note that namespaces can nest only inside other
-	     namespaces, and not inside classes.  So we need only
-	     consider *prefixes* of the string; there is no need to look up
-	     "B::C" separately as a symbol in the previous example. */
-
-	  p2 = p;		/* save for restart */
-	  while (1)
-	    {
-	      /* Extract the class name.  */
-	      p1 = p;
-	      while (p != *argptr && p[-1] == ' ')
-		--p;
-	      copy = (char *) alloca (p - *argptr + 1);
-	      memcpy (copy, *argptr, p - *argptr);
-	      copy[p - *argptr] = 0;
-
-	      /* Discard the class name from the arg.  */
-	      p = p1 + (p1[0] == ':' ? 2 : 1);
-	      while (*p == ' ' || *p == '\t')
-		p++;
-	      *argptr = p;
-
-	      sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
-					 (struct symtab **) NULL);
-
-	      if (sym_class &&
-		  (t = check_typedef (SYMBOL_TYPE (sym_class)),
-		   (TYPE_CODE (t) == TYPE_CODE_STRUCT
-		    || TYPE_CODE (t) == TYPE_CODE_UNION)))
-		{
-		  /* 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
-		    {
-		      p = *argptr;
-		      while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
-			p++;
-		    }
-/*
-   q = operator_chars (*argptr, &q1);
-   if (q1 - q)
-   {
-   char *opname;
-   char *tmp = alloca (q1 - q + 1);
-   memcpy (tmp, q, q1 - q);
-   tmp[q1 - q] = '\0';
-   opname = cplus_mangle_opname (tmp, DMGL_ANSI);
-   if (opname == NULL)
-   {
-   cplusplus_error (saved_arg, "no mangling for \"%s\"\n", tmp);
-   }
-   copy = (char*) alloca (3 + strlen(opname));
-   sprintf (copy, "__%s", opname);
-   p = q1;
-   }
-   else
- */
-		  {
-		    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';
-		  }
-
-		  /* no line number may be specified */
-		  while (*p == ' ' || *p == '\t')
-		    p++;
-		  *argptr = p;
-
-		  sym = 0;
-		  i1 = 0;	/*  counter for the symbol array */
-		  sym_arr = (struct symbol **) alloca (total_number_of_methods (t)
-						* sizeof (struct symbol *));
-
-		  if (destructor_name_p (copy, t))
-		    {
-		      /* Destructors are a special case.  */
-		      int m_index, f_index;
-
-		      if (get_destructor_fn_field (t, &m_index, &f_index))
-			{
-			  struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
-
-			  sym_arr[i1] =
-			    lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
-					   NULL, VAR_NAMESPACE, (int *) NULL,
-					   (struct symtab **) NULL);
-			  if (sym_arr[i1])
-			    i1++;
-			}
-		    }
-		  else
-		    i1 = find_methods (t, copy, sym_arr);
-		  if (i1 == 1)
-		    {
-		      /* There is exactly one field with that name.  */
-		      sym = sym_arr[0];
-
-		      if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
-			{
-			  values.sals = (struct symtab_and_line *)
-			    xmalloc (sizeof (struct symtab_and_line));
-			  values.nelts = 1;
-			  values.sals[0] = find_function_start_sal (sym,
-							      funfirstline);
-			}
-		      else
-			{
-			  values.nelts = 0;
-			}
-		      return values;
-		    }
-		  if (i1 > 0)
-		    {
-		      /* There is more than one field with that name
-		         (overloaded).  Ask the user which one to use.  */
-		      return decode_line_2 (sym_arr, i1, funfirstline, canonical);
-		    }
-		  else
-		    {
-		      char *tmp;
-
-		      if (is_operator_name (copy))
-			{
-			  tmp = (char *) alloca (strlen (copy + 3) + 9);
-			  strcpy (tmp, "operator ");
-			  strcat (tmp, copy + 3);
-			}
-		      else
-			tmp = copy;
-		      if (tmp[0] == '~')
-			cplusplus_error (saved_arg,
-					 "the class `%s' does not have destructor defined\n",
-					 SYMBOL_SOURCE_NAME (sym_class));
-		      else
-			cplusplus_error (saved_arg,
-					 "the class %s does not have any method named %s\n",
-					 SYMBOL_SOURCE_NAME (sym_class), tmp);
-		    }
-		}
-
-	      /* Move pointer up to next possible class/namespace token */
-	      p = p2 + 1;	/* restart with old value +1 */
-	      /* Move pointer ahead to next double-colon */
-	      while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
-		{
-		  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;	/* found double-colon */
-		  else
-		    p++;
-		}
-
-	      if (*p != ':')
-		break;		/* out of the while (1) */
-
-	      p2 = p;		/* save restart for next time around */
-	      *argptr = saved_arg2;	/* restore argptr */
-	    }			/* while (1) */
-
-	  /* Last chance attempt -- check entire name as a symbol */
-	  /* Use "copy" in preparation for jumping out of this block,
-	     to be consistent with usage following the jump target */
-	  copy = (char *) alloca (p - saved_arg2 + 1);
-	  memcpy (copy, saved_arg2, p - saved_arg2);
-	  /* Note: if is_quoted should be true, we snuff out quote here anyway */
-	  copy[p - saved_arg2] = '\000';
-	  /* Set argptr to skip over the name */
-	  *argptr = (*p == '\'') ? p + 1 : p;
-	  /* Look up entire name */
-	  sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
-	  s = (struct symtab *) 0;
-	  if (sym)
-	    return symbol_found (funfirstline, canonical, copy, sym,
-				 NULL, sym_symtab);
-
-	  /* Couldn't find any interpretation as classes/namespaces, so give up */
-	  /* The quotes are important if copy is empty.  */
-	  cplusplus_error (saved_arg,
-			   "Can't find member of namespace, class, struct, or union named \"%s\"\n",
-			   copy);
-	}
-      /*  end of C++  */
-
+	/*  C++ */
+	/*  ... or Java */
+	return decode_compound (argptr, funfirstline, canonical,
+				saved_arg, p);
 
       /* Extract the file name.  */
       p1 = p;
@@ -1281,6 +1057,252 @@ locate_first_half (char **argptr, int *i
 }
 
 
+
+/* 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 (char **argptr, int funfirstline, char ***canonical,
+		 char *saved_arg, char *p)
+{
+  struct symtabs_and_lines values;
+  char *p1, *p2;
+#if 0
+  char *q, *q1;
+#endif
+  char *saved_arg2 = *argptr;
+  char *temp_end;
+  struct symbol *sym;
+  /* The symtab that SYM was found in.  */
+  struct symtab *sym_symtab;
+  char *copy;
+  struct symbol *sym_class;
+  int i1;
+  struct symbol **sym_arr;
+  struct type *t;
+
+  /* First check for "global" namespace specification,
+     of the form "::foo". If found, skip over the colons
+     and jump to normal symbol processing */
+  if (p[0] == ':' 
+      && ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t')))
+    saved_arg2 += 2;
+
+  /* We have what looks like a class or namespace
+     scope specification (A::B), possibly with many
+     levels of namespaces or classes (A::B::C::D).
+
+     Some versions of the HP ANSI C++ compiler (as also possibly
+     other compilers) generate class/function/member names with
+     embedded double-colons if they are inside namespaces. To
+     handle this, we loop a few times, considering larger and
+     larger prefixes of the string as though they were single
+     symbols.  So, if the initially supplied string is
+     A::B::C::D::foo, we have to look up "A", then "A::B",
+     then "A::B::C", then "A::B::C::D", and finally
+     "A::B::C::D::foo" as single, monolithic symbols, because
+     A, B, C or D may be namespaces.
+
+     Note that namespaces can nest only inside other
+     namespaces, and not inside classes.  So we need only
+     consider *prefixes* of the string; there is no need to look up
+     "B::C" separately as a symbol in the previous example. */
+
+  p2 = p;		/* save for restart */
+  while (1)
+    {
+      /* Extract the class name.  */
+      p1 = p;
+      while (p != *argptr && p[-1] == ' ')
+	--p;
+      copy = (char *) alloca (p - *argptr + 1);
+      memcpy (copy, *argptr, p - *argptr);
+      copy[p - *argptr] = 0;
+
+      /* Discard the class name from the arg.  */
+      p = p1 + (p1[0] == ':' ? 2 : 1);
+      while (*p == ' ' || *p == '\t')
+	p++;
+      *argptr = p;
+
+      sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
+				 (struct symtab **) NULL);
+
+      if (sym_class &&
+	  (t = check_typedef (SYMBOL_TYPE (sym_class)),
+	   (TYPE_CODE (t) == TYPE_CODE_STRUCT
+	    || TYPE_CODE (t) == TYPE_CODE_UNION)))
+	{
+	  /* 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
+	    {
+	      p = *argptr;
+	      while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
+		p++;
+	    }
+/*
+   q = operator_chars (*argptr, &q1);
+   if (q1 - q)
+   {
+   char *opname;
+   char *tmp = alloca (q1 - q + 1);
+   memcpy (tmp, q, q1 - q);
+   tmp[q1 - q] = '\0';
+   opname = cplus_mangle_opname (tmp, DMGL_ANSI);
+   if (opname == NULL)
+   {
+   cplusplus_error (saved_arg, "no mangling for \"%s\"\n", tmp);
+   }
+   copy = (char*) alloca (3 + strlen(opname));
+   sprintf (copy, "__%s", opname);
+   p = q1;
+   }
+   else
+ */
+	  {
+	    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';
+	  }
+
+	  /* no line number may be specified */
+	  while (*p == ' ' || *p == '\t')
+	    p++;
+	  *argptr = p;
+
+	  sym = 0;
+	  i1 = 0;	/*  counter for the symbol array */
+	  sym_arr = (struct symbol **) alloca (total_number_of_methods (t)
+					       * sizeof (struct symbol *));
+
+	  if (destructor_name_p (copy, t))
+	    {
+	      /* Destructors are a special case.  */
+	      int m_index, f_index;
+
+	      if (get_destructor_fn_field (t, &m_index, &f_index))
+		{
+		  struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
+
+		  sym_arr[i1] =
+		    lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
+				   NULL, VAR_NAMESPACE, (int *) NULL,
+				   (struct symtab **) NULL);
+		  if (sym_arr[i1])
+		    i1++;
+		}
+	    }
+	  else
+	    i1 = find_methods (t, copy, sym_arr);
+	  if (i1 == 1)
+	    {
+	      /* There is exactly one field with that name.  */
+	      sym = sym_arr[0];
+
+	      if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+		{
+		  values.sals = (struct symtab_and_line *)
+		    xmalloc (sizeof (struct symtab_and_line));
+		  values.nelts = 1;
+		  values.sals[0] = find_function_start_sal (sym,
+							    funfirstline);
+		}
+	      else
+		{
+		  values.nelts = 0;
+		}
+	      return values;
+	    }
+	  if (i1 > 0)
+	    {
+	      /* There is more than one field with that name
+		 (overloaded).  Ask the user which one to use.  */
+	      return decode_line_2 (sym_arr, i1, funfirstline, canonical);
+	    }
+	  else
+	    {
+	      char *tmp;
+
+	      if (is_operator_name (copy))
+		{
+		  tmp = (char *) alloca (strlen (copy + 3) + 9);
+		  strcpy (tmp, "operator ");
+		  strcat (tmp, copy + 3);
+		}
+	      else
+		tmp = copy;
+	      if (tmp[0] == '~')
+		cplusplus_error (saved_arg,
+				 "the class `%s' does not have destructor defined\n",
+				 SYMBOL_SOURCE_NAME (sym_class));
+	      else
+		cplusplus_error (saved_arg,
+				 "the class %s does not have any method named %s\n",
+				 SYMBOL_SOURCE_NAME (sym_class), tmp);
+	    }
+	}
+
+      /* Move pointer up to next possible class/namespace token */
+      p = p2 + 1;	/* restart with old value +1 */
+      /* Move pointer ahead to next double-colon */
+      while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
+	{
+	  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;	/* found double-colon */
+	  else
+	    p++;
+	}
+
+      if (*p != ':')
+	break;		/* out of the while (1) */
+
+      p2 = p;		/* save restart for next time around */
+      *argptr = saved_arg2;	/* restore argptr */
+    }			/* while (1) */
+
+  /* Last chance attempt -- check entire name as a symbol */
+  /* Use "copy" in preparation for jumping out of this block,
+     to be consistent with usage following the jump target */
+  copy = (char *) alloca (p - saved_arg2 + 1);
+  memcpy (copy, saved_arg2, p - saved_arg2);
+  /* Note: if is_quoted should be true, we snuff out quote here anyway */
+  copy[p - saved_arg2] = '\000';
+  /* Set argptr to skip over the name */
+  *argptr = (*p == '\'') ? p + 1 : p;
+  /* Look up entire name */
+  sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
+  if (sym)
+    return symbol_found (funfirstline, canonical, copy, sym,
+			 NULL, sym_symtab);
+
+  /* Couldn't find any interpretation as classes/namespaces, so give up */
+  /* The quotes are important if copy is empty.  */
+  cplusplus_error (saved_arg,
+		   "Can't find member of namespace, class, struct, or union named \"%s\"\n",
+		   copy);
+}
+
+
 
 /* Now come some functions that are called from multiple places within
    decode_line_1.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]