remove long long printf crash
[deliverable/binutils-gdb.git] / gdb / buildsym.c
index 1e569547f142b166c316f39e5697c856c58e8fb1..b104f16e928acf01cf4e3c4968c1b57b5f66a010 100644 (file)
@@ -1,5 +1,5 @@
 /* Support routines for building symbol tables in GDB's internal format.
-   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992
+   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1995, 1996
              Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -16,7 +16,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* This module provides subroutines used for creating and adding to
    the symbol table.  These routines are called from various symbol-
@@ -31,20 +31,38 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "symtab.h"
 #include "symfile.h"           /* Needed for "struct complaint" */
 #include "objfiles.h"
+#include "gdbtypes.h"
 #include "complaints.h"
-#include <string.h>
+#include "gdb_string.h"
 
 /* Ask buildsym.h to define the vars it normally declares `extern'.  */
 #define        EXTERN  /**/
 #include "buildsym.h"          /* Our own declarations */
 #undef EXTERN
 
+/* For cleanup_undefined_types and finish_global_stabs (somewhat
+   questionable--see comment where we call them).  */
+#include "stabsread.h"
+
+/* Pointer to the head of a linked list of symbol blocks which have
+   already been finalized (lexical contexts already closed) and which are
+   just waiting to be built into a blockvector when finalizing the
+   associated symtab. */
+
+static struct pending_block *pending_blocks = NULL;
+
+/* List of free `struct pending' structures for reuse.  */
+
+static struct pending *free_pendings;
+
+/* Non-zero if symtab has line number info.  This prevents an otherwise empty
+   symtab from being tossed.  */
+
+static int have_line_numbers;
+\f
 static int
 compare_line_numbers PARAMS ((const void *, const void *));
 
-static struct blockvector *
-make_blockvector PARAMS ((struct objfile *));
-
 \f
 /* Initial sizes of data structures.  These are realloc'd larger if needed,
    and realloc'd down to the size actually used, when completed.  */
@@ -55,14 +73,20 @@ make_blockvector PARAMS ((struct objfile *));
 \f
 /* Complaints about the symbols we have encountered.  */
 
+struct complaint block_end_complaint =
+  {"block end address less than block start address in %s (patched it)", 0, 0};
+
+struct complaint anon_block_end_complaint =
+  {"block end address 0x%lx less than block start address 0x%lx (patched it)", 0, 0};
+
 struct complaint innerblock_complaint =
   {"inner block not inside outer block in %s", 0, 0};
 
 struct complaint innerblock_anon_complaint =
-  {"inner block not inside outer block", 0, 0};
+  {"inner block (0x%lx-0x%lx) not inside outer block (0x%lx-0x%lx)", 0, 0};
 
 struct complaint blockvector_complaint = 
-  {"block at 0x%x out of order", 0, 0};
+  {"block at 0x%lx out of order", 0, 0};
 
 \f
 /* maintain the lists of symbols and blocks */
@@ -75,6 +99,10 @@ add_symbol_to_list (symbol, listhead)
      struct pending **listhead;
 {
   register struct pending *link;
+
+  /* If this is an alias for another symbol, don't add it.  */
+  if (symbol->ginfo.name && symbol->ginfo.name[0] == '#')
+    return;
       
   /* We keep PENDINGSIZE symbols in each link of the list.
      If we don't have a link with room in it, add a new link.  */
@@ -98,7 +126,8 @@ add_symbol_to_list (symbol, listhead)
   (*listhead)->symbol[(*listhead)->nsyms++] = symbol;
 }
 
-/* Find a symbol on a pending list.  */
+/* Find a symbol named NAME on a LIST.  NAME need not be '\0'-terminated;
+   LENGTH is the length of the name.  */
 
 struct symbol *
 find_symbol_in_list (list, name, length)
@@ -134,9 +163,6 @@ really_free_pendings (foo)
      int foo;
 {
   struct pending *next, *next1;
-#if 0
-  struct pending_block *bnext, *bnext1;
-#endif
 
   for (next = free_pendings; next; next = next1)
     {
@@ -145,14 +171,7 @@ really_free_pendings (foo)
     }
   free_pendings = NULL;
 
-#if 0 /* Now we make the links in the symbol_obstack, so don't free them.  */
-  for (bnext = pending_blocks; bnext; bnext = bnext1)
-    {
-      bnext1 = bnext->next;
-      free ((PTR)bnext);
-    }
-#endif
-  pending_blocks = NULL;
+  free_pending_blocks ();
 
   for (next = file_symbols; next != NULL; next = next1)
     {
@@ -169,6 +188,23 @@ really_free_pendings (foo)
   global_symbols = NULL;
 }
 
+/* This function is called to discard any pending blocks. */
+
+void
+free_pending_blocks ()
+{
+#if 0 /* Now we make the links in the symbol_obstack, so don't free them.  */
+  struct pending_block *bnext, *bnext1;
+
+  for (bnext = pending_blocks; bnext; bnext = bnext1)
+    {
+      bnext1 = bnext->next;
+      free ((PTR)bnext);
+    }
+#endif
+  pending_blocks = NULL;
+}
+
 /* Take one of the lists of symbols and make a block from it.
    Keep the order the symbols have in the list (reversed from the input file).
    Put the block on the list of pending blocks.  */
@@ -221,8 +257,83 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile)
 
   if (symbol)
     {
+      struct type *ftype = SYMBOL_TYPE (symbol);
       SYMBOL_BLOCK_VALUE (symbol) = block;
       BLOCK_FUNCTION (block) = symbol;
+
+      if (TYPE_NFIELDS (ftype) <= 0)
+       {
+         /* No parameter type information is recorded with the function's
+            type.  Set that from the type of the parameter symbols. */
+         int nparams = 0, iparams;
+         struct symbol *sym;
+         for (i = 0; i < BLOCK_NSYMS (block); i++)
+           {
+             sym = BLOCK_SYM (block, i);
+             switch (SYMBOL_CLASS (sym))
+               {
+               case LOC_ARG:
+               case LOC_REF_ARG:
+               case LOC_REGPARM:
+               case LOC_REGPARM_ADDR:
+               case LOC_BASEREG_ARG:
+               case LOC_LOCAL_ARG:
+                 nparams++;
+                 break;
+               case LOC_UNDEF:
+               case LOC_CONST:
+               case LOC_STATIC:
+               case LOC_REGISTER:
+               case LOC_LOCAL:
+               case LOC_TYPEDEF:
+               case LOC_LABEL:
+               case LOC_BLOCK:
+               case LOC_CONST_BYTES:
+               case LOC_BASEREG:
+               case LOC_UNRESOLVED:
+               case LOC_OPTIMIZED_OUT:
+               default:
+                 break;
+               }
+           }
+         if (nparams > 0)
+           {
+             TYPE_NFIELDS (ftype) = nparams;
+             TYPE_FIELDS (ftype) = (struct field *)
+               TYPE_ALLOC (ftype, nparams * sizeof (struct field));
+                                               
+             for (i = iparams = 0; iparams < nparams; i++)
+               {
+                 sym = BLOCK_SYM (block, i);
+                 switch (SYMBOL_CLASS (sym))
+                   {
+                   case LOC_ARG:
+                   case LOC_REF_ARG:
+                   case LOC_REGPARM:
+                   case LOC_REGPARM_ADDR:
+                   case LOC_BASEREG_ARG:
+                   case LOC_LOCAL_ARG:
+                     TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
+                     iparams++;
+                     break;
+                   case LOC_UNDEF:
+                   case LOC_CONST:
+                   case LOC_STATIC:
+                   case LOC_REGISTER:
+                   case LOC_LOCAL:
+                   case LOC_TYPEDEF:
+                   case LOC_LABEL:
+                   case LOC_BLOCK:
+                   case LOC_CONST_BYTES:
+                   case LOC_BASEREG:
+                   case LOC_UNRESOLVED:
+                   case LOC_OPTIMIZED_OUT:
+                   default:
+                     break;
+                   }
+               }
+           }
+       }
     }
   else
     {
@@ -239,6 +350,25 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile)
     }
   *listhead = NULL;
 
+#if 1
+  /* Check to be sure that the blocks have an end address that is
+     greater than starting address */
+
+  if (BLOCK_END (block) < BLOCK_START (block))
+    {
+      if (symbol)
+       {
+         complain (&block_end_complaint, SYMBOL_SOURCE_NAME (symbol));
+       }
+      else
+       {
+         complain (&anon_block_end_complaint, BLOCK_END (block), BLOCK_START (block));
+       }
+      /* Better than nothing */
+      BLOCK_END (block) = BLOCK_START (block);
+    }
+#endif
+
   /* Install this block as the superblock
      of all blocks made since the start of this scope
      that don't have superblocks yet.  */
@@ -262,10 +392,14 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile)
                }
              else
                {
-                 complain (&innerblock_anon_complaint);
+                 complain (&innerblock_anon_complaint, BLOCK_START (pblock->block),
+                           BLOCK_END (pblock->block), BLOCK_START (block),
+                           BLOCK_END (block));
                }
-             BLOCK_START (pblock->block) = BLOCK_START (block);
-             BLOCK_END   (pblock->block) = BLOCK_END   (block);
+             if (BLOCK_START (pblock->block) < BLOCK_START (block))
+               BLOCK_START (pblock->block) = BLOCK_START (block);
+             if (BLOCK_END (pblock->block) > BLOCK_END (block))
+               BLOCK_END (pblock->block) = BLOCK_END (block);
            }
 #endif
          BLOCK_SUPERBLOCK (pblock->block) = block;
@@ -273,31 +407,46 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile)
       opblock = pblock;
     }
 
-  /* Record this block on the list of all blocks in the file.
-     Put it after opblock, or at the beginning if opblock is 0.
-     This puts the block in the list after all its subblocks.  */
+  record_pending_block (objfile, block, opblock);
+}
+
+/* Record BLOCK on the list of all blocks in the file.  Put it after
+   OPBLOCK, or at the beginning if opblock is NULL.  This puts the block
+   in the list after all its subblocks.
+
+   Allocate the pending block struct in the symbol_obstack to save
+   time.  This wastes a little space.  FIXME: Is it worth it?  */
+
+void
+record_pending_block (objfile, block, opblock)
+     struct objfile* objfile;
+     struct block *block;
+     struct pending_block *opblock;
+{
+  register struct pending_block *pblock;
 
-  /* Allocate in the symbol_obstack to save time.
-     It wastes a little space.  */
   pblock = (struct pending_block *)
-    obstack_alloc (&objfile -> symbol_obstack,
-                  sizeof (struct pending_block));
-  pblock->block = block;
+    obstack_alloc (&objfile -> symbol_obstack, sizeof (struct pending_block));
+  pblock -> block = block;
   if (opblock)
     {
-      pblock->next = opblock->next;
-      opblock->next = pblock;
+      pblock -> next = opblock -> next;
+      opblock -> next = pblock;
     }
   else
     {
-      pblock->next = pending_blocks;
+      pblock -> next = pending_blocks;
       pending_blocks = pblock;
     }
 }
 
-static struct blockvector *
+/* Note that this is only used in this file and in dstread.c, which should be
+   fixed to not need direct access to this function.  When that is done, it can
+   be made static again. */
+
+struct blockvector *
 make_blockvector (objfile)
-      struct objfile *objfile;
+     struct objfile *objfile;
 {
   register struct pending_block *next;
   register struct blockvector *blockvector;
@@ -346,8 +495,17 @@ make_blockvector (objfile)
          if (BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i-1))
              > BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i)))
            {
+
+             /* FIXME-32x64: loses if CORE_ADDR doesn't fit in a
+                long.  Possible solutions include a version of
+                complain which takes a callback, a
+                sprintf_address_numeric to match
+                print_address_numeric, or a way to set up a GDB_FILE
+                * which causes sprintf rather than fprintf to be
+                called.  */
+
              complain (&blockvector_complaint, 
-                       BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i)));
+                       (unsigned long) BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i)));
            }
        }
     }
@@ -358,7 +516,9 @@ make_blockvector (objfile)
 
 \f
 /* Start recording information about source code that came from an included
-   (or otherwise merged-in) source file with a different name.  */
+   (or otherwise merged-in) source file with a different name.  NAME is
+   the name of the file (cannot be NULL), DIRNAME is the directory in which
+   it resides (or NULL if not known).  */
 
 void
 start_subfile (name, dirname)
@@ -389,8 +549,9 @@ start_subfile (name, dirname)
   current_subfile = subfile;
 
   /* Save its name and compilation directory name */
-  subfile->name = strdup (name);
-  subfile->dirname = (dirname == NULL) ? NULL : strdup (dirname);
+  subfile->name = (name == NULL) ? NULL : savestring (name, strlen (name));
+  subfile->dirname =
+    (dirname == NULL) ? NULL : savestring (dirname, strlen (dirname));
   
   /* Initialize line-number recording for this subfile.  */
   subfile->line_vector = NULL;
@@ -412,6 +573,41 @@ start_subfile (name, dirname)
     {
       subfile->language = subfile->next->language;
     }
+
+  /* Initialize the debug format string to NULL.  We may supply it
+     later via a call to record_debugformat. */
+  subfile->debugformat = NULL;
+
+  /* cfront output is a C program, so in most ways it looks like a C
+     program.  But to demangle we need to set the language to C++.  We
+     can distinguish cfront code by the fact that it has #line
+     directives which specify a file name ending in .C.
+
+     So if the filename of this subfile ends in .C, then change the language
+     of any pending subfiles from C to C++.  We also accept any other C++
+     suffixes accepted by deduce_language_from_filename (in particular,
+     some people use .cxx with cfront).  */
+  /* Likewise for f2c.  */
+
+  if (subfile->name)
+    {
+      struct subfile *s;
+      enum language sublang = deduce_language_from_filename (subfile->name);
+
+      if (sublang == language_cplus || sublang == language_fortran)
+       for (s = subfiles; s != NULL; s = s->next)
+         if (s->language == language_c)
+           s->language = sublang;
+    }
+
+  /* And patch up this file if necessary.  */
+  if (subfile->language == language_c
+      && subfile->next != NULL
+      && (subfile->next->language == language_cplus
+         || subfile->next->language == language_fortran))
+    {
+      subfile->language = subfile->next->language;
+    }
 }
 
 /* For stabs readers, the first N_SO symbol is assumed to be the source
@@ -435,7 +631,8 @@ patch_subfile_names (subfile, name)
       && subfile->name[strlen(subfile->name)-1] == '/')
     {
       subfile->dirname = subfile->name;
-      subfile->name = strdup (name);
+      subfile->name = savestring (name, strlen (name));
+      last_source_file = name;
 
       /* Default the source language to whatever can be deduced from
         the filename.  If nothing can be deduced (such as for a C/C++
@@ -495,7 +692,8 @@ pop_subfile ()
 }
 
 \f
-/* Manage the vector of line numbers for each subfile.  */
+/* Add a linetable entry for line number LINE and address PC to the line
+   vector for SUBFILE.  */
 
 void
 record_line (subfile, line, pc)
@@ -519,6 +717,7 @@ record_line (subfile, line, pc)
        xmalloc (sizeof (struct linetable)
          + subfile->line_vector_length * sizeof (struct linetable_entry));
       subfile->line_vector->nitems = 0;
+      have_line_numbers = 1;
     }
 
   if (subfile->line_vector->nitems + 1 >= subfile->line_vector_length)
@@ -538,11 +737,23 @@ record_line (subfile, line, pc)
 
 static int
 compare_line_numbers (ln1p, ln2p)
-     const PTR ln1p;
-     const PTR ln2p;
+     const void *ln1p;
+     const void *ln2p;
 {
-  return (((struct linetable_entry *) ln1p) -> line -
-         ((struct linetable_entry *) ln2p) -> line);
+  struct linetable_entry *ln1 = (struct linetable_entry *) ln1p;
+  struct linetable_entry *ln2 = (struct linetable_entry *) ln2p;
+
+  /* Note: this code does not assume that CORE_ADDRs can fit in ints.
+     Please keep it that way.  */
+  if (ln1->pc < ln2->pc)
+    return -1;
+
+  if (ln1->pc > ln2->pc)
+    return 1;
+
+  /* If pc equal, sort by line.  I'm not sure whether this is optimum
+     behavior (see comment at struct linetable in symtab.h).  */
+  return ln1->line - ln2->line;
 }
 
 \f
@@ -563,6 +774,7 @@ start_symtab (name, dirname, start_addr)
   file_symbols = NULL;
   global_symbols = NULL;
   within_function = 0;
+  have_line_numbers = 0;
 
   /* Context stack is initially empty.  Allocate first one with room for
      10 levels; reuse it forever afterward.  */
@@ -588,6 +800,8 @@ start_symtab (name, dirname, start_addr)
    for that file and put it in the list of all such.
 
    END_ADDR is the address of the end of the file's text.
+   SECTION is the section number (in objfile->section_offsets) of
+   the blockvector and linetable.
 
    Note that it is possible for end_symtab() to return NULL.  In particular,
    for the DWARF case at least, it will return NULL when it finds a
@@ -597,13 +811,12 @@ start_symtab (name, dirname, start_addr)
    because then gdb will never know about this empty file (FIXME). */
 
 struct symtab *
-end_symtab (end_addr, sort_pending, sort_linevec, objfile)
+end_symtab (end_addr, objfile, section)
      CORE_ADDR end_addr;
-     int sort_pending;
-     int sort_linevec;
      struct objfile *objfile;
+     int section;
 {
-  register struct symtab *symtab;
+  register struct symtab *symtab = NULL;
   register struct blockvector *blockvector;
   register struct subfile *subfile;
   register struct context_stack *cstk;
@@ -614,28 +827,29 @@ end_symtab (end_addr, sort_pending, sort_linevec, objfile)
 
   if (context_stack_depth > 0)
     {
-      context_stack_depth--;
-      cstk = &context_stack[context_stack_depth];
+      cstk = pop_context();
       /* Make a block for the local symbols within.  */
       finish_block (cstk->name, &local_symbols, cstk->old_blocks,
                    cstk->start_addr, end_addr, objfile);
 
-      /* Debug: if context stack still has something in it,
-        we are in trouble.  */
       if (context_stack_depth > 0)
        {
-         abort ();
+         /* This is said to happen with SCO.  The old coffread.c code
+            simply emptied the context stack, so we do the same.  FIXME:
+            Find out why it is happening.  This is not believed to happen
+            in most cases (even for coffread.c); it used to be an abort().  */
+         static struct complaint msg =
+           {"Context stack not empty in end_symtab", 0, 0};
+         complain (&msg);
+         context_stack_depth = 0;
        }
     }
 
-  /* It is unfortunate that in xcoff, pending blocks might not be ordered
-     in this stage. Especially, blocks for static functions will show up at
-     the end.  We need to sort them, so tools like `find_pc_function' and
-     `find_pc_block' can work reliably. */
-
-  if (sort_pending && pending_blocks)
+  /* Reordered executables may have out of order pending blocks; if
+     OBJF_REORDERED is true, then sort the pending blocks.  */
+  if ((objfile->flags & OBJF_REORDERED) && pending_blocks)
     {
-      /* FIXME!  Remove this horrid bubble sort and use qsort!!! */
+      /* FIXME!  Remove this horrid bubble sort and use merge sort!!! */
       int swapped;
       do
        {
@@ -665,13 +879,20 @@ end_symtab (end_addr, sort_pending, sort_linevec, objfile)
   /* Cleanup any undefined types that have been left hanging around
      (this needs to be done before the finish_blocks so that
      file_symbols is still good).
-     FIXME:  Stabs specific. */
+
+     Both cleanup_undefined_types and finish_global_stabs are stabs
+     specific, but harmless for other symbol readers, since on gdb
+     startup or when finished reading stabs, the state is set so these
+     are no-ops.  FIXME: Is this handled right in case of QUIT?  Can
+     we make this cleaner?  */
+
   cleanup_undefined_types ();
   finish_global_stabs (objfile);
 
   if (pending_blocks == NULL
       && file_symbols == NULL
-      && global_symbols == NULL)
+      && global_symbols == NULL
+      && have_line_numbers == 0)
     {
       /* Ignore symtabs that have no functions with real debugging info */
       blockvector = NULL;
@@ -695,7 +916,7 @@ end_symtab (end_addr, sort_pending, sort_linevec, objfile)
 
   for (subfile = subfiles; subfile; subfile = nextsub)
     {
-      int linetablesize;
+      int linetablesize = 0;
       /* If we have blocks of symbols, make a symtab.
         Otherwise, just ignore this file and any line number info in it.  */
       symtab = NULL;
@@ -703,13 +924,21 @@ end_symtab (end_addr, sort_pending, sort_linevec, objfile)
        {
          if (subfile->line_vector)
            {
-             /* First, shrink the linetable to make more memory.  */
              linetablesize = sizeof (struct linetable) +
                subfile->line_vector->nitems * sizeof (struct linetable_entry);
+#if 0
+             /* I think this is artifact from before it went on the obstack.
+                I doubt we'll need the memory between now and when we
+                free it later in this function.  */
+             /* First, shrink the linetable to make more memory.  */
              subfile->line_vector = (struct linetable *)
                xrealloc ((char *) subfile->line_vector, linetablesize);
+#endif
 
-             if (sort_linevec)
+             /* Like the pending blocks, the line table may be scrambled
+                in reordered executables.  Sort it if OBJF_REORDERED is
+                true.  */
+             if (objfile->flags & OBJF_REORDERED)
                qsort (subfile->line_vector->item,
                       subfile->line_vector->nitems,
                       sizeof (struct linetable_entry), compare_line_numbers);
@@ -731,6 +960,7 @@ end_symtab (end_addr, sort_pending, sort_linevec, objfile)
            {
              symtab->linetable = NULL;
            }
+         symtab->block_line_section = section;
          if (subfile->dirname)
            {
              /* Reallocate the dirname on the symbol obstack */
@@ -753,14 +983,19 @@ end_symtab (end_addr, sort_pending, sort_linevec, objfile)
             language it is from things we found in the symbols. */
          symtab->language = subfile->language;
 
-#ifdef IBM6000_TARGET
-         /* In case we need to duplicate symbol tables (to represent include
-            files), and in case our system needs relocation, we want to
-            relocate the main symbol table node only (for the main file,
-            not for the include files). */
+         /* Save the debug format string (if any) in the symtab */
+         if (subfile -> debugformat != NULL)
+           {
+             symtab->debugformat = obsavestring (subfile->debugformat,
+                                                 strlen (subfile->debugformat),
+                                                 &objfile -> symbol_obstack);
+           }
+
+         /* All symtabs for the main file and the subfiles share a
+            blockvector, so we need to clear primary for everything but
+            the main file.  */
 
-         symtab->nonreloc = TRUE;
-#endif
+         symtab->primary = 0;
        }
       if (subfile->name != NULL)
        {
@@ -774,19 +1009,20 @@ end_symtab (end_addr, sort_pending, sort_linevec, objfile)
        {
          free ((PTR) subfile->line_vector);
        }
+      if (subfile->debugformat != NULL)
+       {
+         free ((PTR) subfile->debugformat);
+       }
 
       nextsub = subfile->next;
       free ((PTR)subfile);
     }
 
-#ifdef IBM6000_TARGET
-  /* all include symbol tables are non-relocatable, except the main source
-     file's. */
+  /* Set this for the main source file.  */
   if (symtab)
     {
-      symtab->nonreloc = FALSE;
+      symtab->primary = 1;
     }
-#endif
 
   last_source_file = NULL;
   current_subfile = NULL;
@@ -825,6 +1061,45 @@ push_context (desc, valu)
   return (new);
 }
 
+\f
+/* Compute a small integer hash code for the given name. */
+
+int
+hashname (name)
+     char *name;
+{
+  register char *p = name;
+  register int total = p[0];
+  register int c;
+
+  c = p[1];
+  total += c << 2;
+  if (c)
+    {
+      c = p[2];
+      total += c << 4;
+      if (c)
+       {
+         total += p[3] << 6;
+       }
+    }
+
+  /* Ensure result is positive.  */
+  if (total < 0)
+    {
+      total += (1000 << 6);
+    }
+  return (total % HASHSIZE);
+}
+
+\f
+void
+record_debugformat (format)
+     char *format;
+{
+  current_subfile -> debugformat = savestring (format, strlen (format));
+}
+
 \f
 /* Initialize anything that needs initializing when starting to read
    a fresh piece of a symbol file, e.g. reading in the stuff corresponding
This page took 0.063781 seconds and 4 git commands to generate.