* serial.h (SERIAL_SET_TTY_STATE): Comment return value.
[deliverable/binutils-gdb.git] / gdb / symtab.c
index 582ca04696b5490ee220c52e710e9a581d182fad..3e751db5e693b612768846516456faa8f52dc806 100644 (file)
@@ -1,6 +1,6 @@
 /* Symbol table lookup for the GNU debugger, GDB.
-   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992
-   Free Software Foundation, Inc.
+   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994
+             Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -193,6 +193,10 @@ lookup_symtab (name)
   s = lookup_symtab_1 (name);
   if (s) return s;
 
+#if 0
+  /* This screws c-exp.y:yylex if there is both a type "tree" and a symtab
+     "tree.c".  */
+
   /* If name not found as specified, see if adding ".c" helps.  */
   /* Why is this?  Is it just a user convenience?  (If so, it's pretty
      questionable in the presence of C++, FORTRAN, etc.).  It's not in
@@ -203,6 +207,7 @@ lookup_symtab (name)
   strcat (copy, ".c");
   s = lookup_symtab_1 (copy);
   if (s) return s;
+#endif /* 0 */
 
   /* We didn't find anything; die.  */
   return 0;
@@ -260,6 +265,11 @@ gdb_mangle_name (type, i, j)
   char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
   char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
   char *newname = type_name_no_tag (type);
+
+  /* Does the form of physname indicate that it is the full mangled name
+     of a constructor (not just the args)?  */
+  int is_full_physname_constructor;
+
   int is_constructor;
   int is_destructor = DESTRUCTOR_PREFIX_P (physname);
   /* Need a new type prefix.  */
@@ -268,17 +278,19 @@ gdb_mangle_name (type, i, j)
   char buf[20];
   int len = (newname == NULL ? 0 : strlen (newname));
 
-  is_constructor = newname && STREQ(field_name, newname);
-  if (!is_constructor)
-    is_constructor = (physname[0]=='_' && physname[1]=='_' && 
-               (isdigit(physname[2]) || physname[2]=='Q' || physname[2]=='t'));
-  if (!is_constructor)
-    is_constructor = (strncmp(physname, "__ct", 4) == 0); 
+  is_full_physname_constructor = 
+    ((physname[0]=='_' && physname[1]=='_' && 
+      (isdigit(physname[2]) || physname[2]=='Q' || physname[2]=='t'))
+     || (strncmp(physname, "__ct", 4) == 0));
+
+  is_constructor =
+    is_full_physname_constructor || (newname && STREQ(field_name, newname));
+
   if (!is_destructor)
     is_destructor = (strncmp(physname, "__dt", 4) == 0); 
 
 #ifndef GCC_MANGLE_BUG
-  if (is_destructor)
+  if (is_destructor || is_full_physname_constructor)
     {
       mangled_name = (char*) xmalloc(strlen(physname)+1);
       strcpy(mangled_name, physname);
@@ -413,6 +425,21 @@ find_pc_psymbol (psymtab, pc)
 
   best_pc = psymtab->textlow - 1;
 
+  /* Search the global symbols as well as the static symbols, so that
+     find_pc_partial_function doesn't use a minimal symbol and thus
+     cache a bad endaddr.  */
+  for (p = psymtab->objfile->global_psymbols.list + psymtab->globals_offset;
+       (p - (psymtab->objfile->global_psymbols.list + psymtab->globals_offset)
+       < psymtab->n_global_syms);
+       p++)
+    if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE
+       && SYMBOL_CLASS (p) == LOC_BLOCK
+       && pc >= SYMBOL_VALUE_ADDRESS (p)
+       && SYMBOL_VALUE_ADDRESS (p) > best_pc)
+      {
+       best_pc = SYMBOL_VALUE_ADDRESS (p);
+       best = p;
+      }
   for (p = psymtab->objfile->static_psymbols.list + psymtab->statics_offset;
        (p - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset)
        < psymtab->n_static_syms);
@@ -442,6 +469,16 @@ find_pc_psymbol (psymtab, pc)
    BLOCK_FOUND is set to the block in which NAME is found (in the case of
    a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */
 
+/* This function has a bunch of loops in it and it would seem to be
+   attractive to put in some QUIT's (though I'm not really sure
+   whether it can run long enough to be really important).  But there
+   are a few calls for which it would appear to be bad news to quit
+   out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c, and
+   nindy_frame_chain_valid in nindy-tdep.c.  (Note that there is C++
+   code below which can error(), but that probably doesn't affect
+   these calls since they are looking for a known variable and thus
+   can probably assume it will never hit the C++ code).  */
+
 struct symbol *
 lookup_symbol (name, block, namespace, is_a_field_of_this, symtab)
      const char *name;
@@ -999,6 +1036,80 @@ find_pc_symtab (pc)
     }
   return (s);
 }
+\f
+/* Find the closest symbol value (of any sort -- function or variable)
+   for a given address value.  Slow but complete.  */
+
+struct symbol *
+find_addr_symbol (addr, symtabp, symaddrp)
+     CORE_ADDR addr;
+     struct symtab **symtabp;
+     CORE_ADDR *symaddrp;
+{
+  struct symtab *symtab, *best_symtab;
+  struct objfile *objfile;
+  register int bot, top;
+  register struct symbol *sym;
+  register CORE_ADDR sym_addr;
+  struct block *block;
+  int blocknum;
+
+  /* Info on best symbol seen so far */
+
+  register CORE_ADDR best_sym_addr = 0;
+  struct symbol *best_sym = 0;
+
+  /* FIXME -- we should pull in all the psymtabs, too!  */
+  ALL_SYMTABS (objfile, symtab)
+    {
+      /* Search the global and static blocks in this symtab for
+        the closest symbol-address to the desired address.  */
+
+      for (blocknum = GLOBAL_BLOCK; blocknum <= STATIC_BLOCK; blocknum++)
+       {
+         QUIT;
+         block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), blocknum);
+         top = BLOCK_NSYMS (block);
+         for (bot = 0; bot < top; bot++)
+           {
+             sym = BLOCK_SYM (block, bot);
+             switch (SYMBOL_CLASS (sym))
+               {
+               case LOC_STATIC:        
+               case LOC_LABEL: 
+                 sym_addr = SYMBOL_VALUE_ADDRESS (sym);
+                 break;
+
+               case LOC_BLOCK:
+                 sym_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+                 break;
+
+               default:
+                 continue;
+               }
+
+               if (sym_addr <= addr)
+                 if (sym_addr > best_sym_addr)
+                   {
+                     /* Quit if we found an exact match.  */
+                     best_sym = sym;
+                     best_sym_addr = sym_addr;
+                     best_symtab = symtab;
+                     if (sym_addr == addr)
+                       goto done;
+                   }
+           }
+       }
+    }
+
+ done:
+  if (symtabp)
+    *symtabp = best_symtab;
+  if (symaddrp)
+    *symaddrp = best_sym_addr;
+  return best_sym;
+}
+
 
 /* Find the source file and line number for a given PC value.
    Return a structure containing a symtab pointer, a line number,
@@ -1284,9 +1395,6 @@ find_line_pc_range (sal, startptr, endptr)
      struct symtab_and_line sal;
      CORE_ADDR *startptr, *endptr;
 {
-  struct linetable *l;
-  int ind;
-  int exact_match;             /* did we get an exact linenumber match */
   CORE_ADDR startaddr;
   struct symtab_and_line found_sal;
 
@@ -1507,8 +1615,18 @@ find_methods (t, name, sym_arr)
        {
          int field_counter;
          struct fn_field *f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
          char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
+         char dem_opname[64];
+
+          if (strncmp(method_name, "__", 2)==0 ||
+           strncmp(method_name, "op", 2)==0 ||
+           strncmp(method_name, "type", 4)==0 )
+           {
+             if (cplus_demangle_opname(method_name, dem_opname, DMGL_ANSI))
+               method_name = dem_opname;
+             else if (cplus_demangle_opname(method_name, dem_opname, 0))
+               method_name = dem_opname; 
+           }
          if (STREQ (name, method_name))
            /* Find all the fields with that name.  */
            for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
@@ -1540,7 +1658,8 @@ find_methods (t, name, sym_arr)
                  {
                    fputs_filtered("(Cannot find method ", gdb_stdout);
                    fprintf_symbol_filtered (gdb_stdout, phys_name,
-                                            language_cplus, DMGL_PARAMS);
+                                            language_cplus,
+                                            DMGL_PARAMS | DMGL_ANSI);
                    fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
                  }
              }
@@ -1640,6 +1759,11 @@ build_canonical_line_spec (sal, symname, canonical)
    if no file is validly specified.  Callers must check that.
    Also, the line number returned may be invalid.  */
 
+/* We allow single quotes in various places.  This is a hideous
+   kludge, which exists because the completer can't yet deal with the
+   lack of single quotes.  FIXME: write a linespec_completer which we
+   can use as appropriate instead of make_symbol_completion_list.  */
+
 struct symtabs_and_lines
 decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
      char **argptr;
@@ -1680,7 +1804,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
   struct symtab_and_line val;
 #endif
   register char *p, *p1;
-  char *q, *q1;
+  char *q, *q1, *pp;
   register struct symtab *s;
 
   register struct symbol *sym;
@@ -1692,7 +1816,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
   char *copy;
   struct symbol *sym_class;
   int i1;
-  int is_quoted;
+  int is_quoted, has_parens;
   struct symbol **sym_arr;
   struct type *t;
   char *saved_arg = *argptr;
@@ -1727,19 +1851,33 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
   /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
 
   s = NULL;
-  is_quoted = (strchr (gdb_completer_quote_characters, **argptr) != NULL);
+  is_quoted = (strchr(gdb_completer_quote_characters, **argptr) != NULL);
+  has_parens = (( pp = strchr(*argptr, '(')) != NULL  &&
+                (pp = strchr(pp, ')')) != NULL);
 
   for (p = *argptr; *p; p++)
     {
+      if (p[0] == '<') 
+       {
+         while(!++p && *p != '>');
+         if (!p)
+           {
+             /* FIXME: Why warning() and then return_to_top_level?
+                What's wrong with error()?  */
+             warning("non-matching '<' and '>' in command");
+             return_to_top_level (RETURN_ERROR);
+           }
+       }
       if (p[0] == ':' || p[0] == ' ' || p[0] == '\t')
        break;
     }
   while (p[0] == ' ' || p[0] == '\t') p++;
 
-  if ((p[0] == ':') && !is_quoted)
+  if ((p[0] == ':') && !has_parens)
     {
 
       /*  C++  */
+      if (is_quoted) *argptr = *argptr+1;
       if (p[1] ==':')
        {
          /* Extract the class name.  */
@@ -1762,11 +1900,19 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
               || TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_UNION))
            {
              /* Arg token is not digits => try it as a function name
-                Find the next token (everything up to end or next whitespace). */
-             p = *argptr;
-             while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p !=':') p++;
+                Find the next token(everything up to end or next blank). */
+             if (strchr(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;
@@ -1785,10 +1931,13 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
                  p = q1;
                }
              else
+*/
                {
-                 copy = (char *) alloca (p - *argptr + 1 + (q1 - q));
+                 copy = (char *) alloca (p - *argptr + 1 );
                  memcpy (copy, *argptr, p - *argptr);
                  copy[p - *argptr] = '\0';
+                 if (strchr(gdb_completer_quote_characters, copy[p-*argptr-1]) != NULL)
+                   copy[p - *argptr -1] = '\0';
                }
 
              /* no line number may be specified */
@@ -1914,12 +2063,12 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
 
   /* Check whether arg is all digits (and sign) */
 
-  p = *argptr;
-  if (*p == '-' || *p == '+') p++;
-  while (*p >= '0' && *p <= '9')
-    p++;
+  q = *argptr;
+  if (*q == '-' || *q == '+') q++;
+  while (*q >= '0' && *q <= '9')
+    q++;
 
-  if (p != *argptr && (*p == 0 || *p == ' ' || *p == '\t' || *p == ','))
+  if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
     {
       /* We found a token consisting of all digits -- at least one digit.  */
       enum sign {none, plus, minus} sign = none;
@@ -1947,13 +2096,13 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
       switch (sign)
        {
        case plus:
-         if (p == *argptr)
+         if (q == *argptr)
            val.line = 5;
          if (s == 0)
            val.line = default_line + val.line;
          break;
        case minus:
-         if (p == *argptr)
+         if (q == *argptr)
            val.line = 15;
          if (s == 0)
            val.line = default_line - val.line;
@@ -1964,8 +2113,8 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
          break;        /* No need to adjust val.line.  */
        }
 
-      while (*p == ' ' || *p == '\t') p++;
-      *argptr = p;
+      while (*q == ' ' || *q == '\t') q++;
+      *argptr = q;
       if (s == 0)
        s = default_symtab;
       val.symtab = s;
@@ -1981,9 +2130,21 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical)
   /* Arg token is not digits => try it as a variable name
      Find the next token (everything up to end or next whitespace).  */
 
-  p = skip_quoted (*argptr);
-  if (is_quoted && p[-1] != '\'')
-    error ("Unmatched single quote.");
+  if (is_quoted)
+    {
+      p = skip_quoted (*argptr);
+      if (p[-1] != '\'')
+        error ("Unmatched single quote.");
+    }
+  else if (has_parens)
+    {
+      p = pp+1;
+    }
+  else 
+    {
+      p = skip_quoted(*argptr);
+    }
+
   copy = (char *) alloca (p - *argptr + 1);
   memcpy (copy, *argptr, p - *argptr);
   copy[p - *argptr] = '\0';
This page took 0.028804 seconds and 4 git commands to generate.