Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elf-strtab.c
index 3bd5531a81d9bf4026b772a00694a14dc8def034..35b821953df67cc503ccb349c054be1afecf6095 100644 (file)
@@ -1,12 +1,12 @@
 /* ELF strtab with GC and suffix merging support.
 /* ELF strtab with GC and suffix merging support.
-   Copyright 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2001-2020 Free Software Foundation, Inc.
    Written by Jakub Jelinek <jakub@redhat.com>.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    Written by Jakub Jelinek <jakub@redhat.com>.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 
-#include "bfd.h"
 #include "sysdep.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "hashtab.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "hashtab.h"
 struct elf_strtab_hash_entry
 {
   struct bfd_hash_entry root;
 struct elf_strtab_hash_entry
 {
   struct bfd_hash_entry root;
-  /* Length of this entry.  */
-  unsigned int len;
+  /* Length of this entry.  This includes the zero terminator.  */
+  int len;
   unsigned int refcount;
   union {
     /* Index within the merged section.  */
     bfd_size_type index;
   unsigned int refcount;
   union {
     /* Index within the merged section.  */
     bfd_size_type index;
-    /* Entry this is a suffix of (if len is 0).  */
+    /* Entry this is a suffix of (if len < 0).  */
     struct elf_strtab_hash_entry *suffix;
     struct elf_strtab_hash_entry *suffix;
-    struct elf_strtab_hash_entry *next;
   } u;
 };
 
   } u;
 };
 
@@ -48,66 +48,61 @@ struct elf_strtab_hash
 {
   struct bfd_hash_table table;
   /* Next available index.  */
 {
   struct bfd_hash_table table;
   /* Next available index.  */
-  bfd_size_type size;
+  size_t size;
   /* Number of array entries alloced.  */
   /* Number of array entries alloced.  */
-  bfd_size_type alloced;
+  size_t alloced;
   /* Final strtab size.  */
   bfd_size_type sec_size;
   /* Array of pointers to strtab entries.  */
   struct elf_strtab_hash_entry **array;
 };
 
   /* Final strtab size.  */
   bfd_size_type sec_size;
   /* Array of pointers to strtab entries.  */
   struct elf_strtab_hash_entry **array;
 };
 
-static struct bfd_hash_entry *elf_strtab_hash_newfunc
-  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static int cmplengthentry PARAMS ((const PTR, const PTR));
-static int last4_eq PARAMS ((const PTR, const PTR));
-
 /* Routine to create an entry in a section merge hashtab.  */
 
 static struct bfd_hash_entry *
 /* Routine to create an entry in a section merge hashtab.  */
 
 static struct bfd_hash_entry *
-elf_strtab_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+elf_strtab_hash_newfunc (struct bfd_hash_entry *entry,
+                        struct bfd_hash_table *table,
+                        const char *string)
 {
 {
-  struct elf_strtab_hash_entry *ret = (struct elf_strtab_hash_entry *) entry;
-
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
-  if (ret == (struct elf_strtab_hash_entry *) NULL)
-    ret = ((struct elf_strtab_hash_entry *)
-          bfd_hash_allocate (table, sizeof (struct elf_strtab_hash_entry)));
-  if (ret == (struct elf_strtab_hash_entry *) NULL)
+  if (entry == NULL)
+    entry = (struct bfd_hash_entry *)
+       bfd_hash_allocate (table, sizeof (struct elf_strtab_hash_entry));
+  if (entry == NULL)
     return NULL;
 
   /* Call the allocation method of the superclass.  */
     return NULL;
 
   /* Call the allocation method of the superclass.  */
-  ret = ((struct elf_strtab_hash_entry *)
-        bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+  entry = bfd_hash_newfunc (entry, table, string);
 
 
-  if (ret)
+  if (entry)
     {
       /* Initialize the local fields.  */
     {
       /* Initialize the local fields.  */
+      struct elf_strtab_hash_entry *ret;
+
+      ret = (struct elf_strtab_hash_entry *) entry;
       ret->u.index = -1;
       ret->refcount = 0;
       ret->len = 0;
     }
 
       ret->u.index = -1;
       ret->refcount = 0;
       ret->len = 0;
     }
 
-  return (struct bfd_hash_entry *)ret;
+  return entry;
 }
 
 /* Create a new hash table.  */
 
 struct elf_strtab_hash *
 }
 
 /* Create a new hash table.  */
 
 struct elf_strtab_hash *
-_bfd_elf_strtab_init ()
+_bfd_elf_strtab_init (void)
 {
   struct elf_strtab_hash *table;
 {
   struct elf_strtab_hash *table;
-  bfd_size_type amt = sizeof (struct elf_strtab_hash);
+  size_t amt = sizeof (struct elf_strtab_hash);
 
   table = (struct elf_strtab_hash *) bfd_malloc (amt);
   if (table == NULL)
     return NULL;
 
 
   table = (struct elf_strtab_hash *) bfd_malloc (amt);
   if (table == NULL)
     return NULL;
 
-  if (! bfd_hash_table_init (&table->table, elf_strtab_hash_newfunc))
+  if (!bfd_hash_table_init (&table->table, elf_strtab_hash_newfunc,
+                           sizeof (struct elf_strtab_hash_entry)))
     {
       free (table);
       return NULL;
     {
       free (table);
       return NULL;
@@ -117,8 +112,8 @@ _bfd_elf_strtab_init ()
   table->size = 1;
   table->alloced = 64;
   amt = sizeof (struct elf_strtab_hasn_entry *);
   table->size = 1;
   table->alloced = 64;
   amt = sizeof (struct elf_strtab_hasn_entry *);
-  table->array = (struct elf_strtab_hash_entry **)
-                bfd_malloc (table->alloced * amt);
+  table->array = ((struct elf_strtab_hash_entry **)
+                 bfd_malloc (table->alloced * amt));
   if (table->array == NULL)
     {
       free (table);
   if (table->array == NULL)
     {
       free (table);
@@ -133,8 +128,7 @@ _bfd_elf_strtab_init ()
 /* Free a strtab.  */
 
 void
 /* Free a strtab.  */
 
 void
-_bfd_elf_strtab_free (tab)
-     struct elf_strtab_hash *tab;
+_bfd_elf_strtab_free (struct elf_strtab_hash *tab)
 {
   bfd_hash_table_free (&tab->table);
   free (tab->array);
 {
   bfd_hash_table_free (&tab->table);
   free (tab->array);
@@ -144,11 +138,10 @@ _bfd_elf_strtab_free (tab)
 /* Get the index of an entity in a hash table, adding it if it is not
    already present.  */
 
 /* Get the index of an entity in a hash table, adding it if it is not
    already present.  */
 
-bfd_size_type
-_bfd_elf_strtab_add (tab, str, copy)
-     struct elf_strtab_hash *tab;
-     const char *str;
-     bfd_boolean copy;
+size_t
+_bfd_elf_strtab_add (struct elf_strtab_hash *tab,
+                    const char *str,
+                    bfd_boolean copy)
 {
   register struct elf_strtab_hash_entry *entry;
 
 {
   register struct elf_strtab_hash_entry *entry;
 
@@ -162,20 +155,22 @@ _bfd_elf_strtab_add (tab, str, copy)
          bfd_hash_lookup (&tab->table, str, TRUE, copy);
 
   if (entry == NULL)
          bfd_hash_lookup (&tab->table, str, TRUE, copy);
 
   if (entry == NULL)
-    return (bfd_size_type) -1;
+    return (size_t) -1;
 
   entry->refcount++;
   if (entry->len == 0)
     {
       entry->len = strlen (str) + 1;
 
   entry->refcount++;
   if (entry->len == 0)
     {
       entry->len = strlen (str) + 1;
+      /* 2G strings lose.  */
+      BFD_ASSERT (entry->len > 0);
       if (tab->size == tab->alloced)
        {
          bfd_size_type amt = sizeof (struct elf_strtab_hash_entry *);
          tab->alloced *= 2;
          tab->array = (struct elf_strtab_hash_entry **)
       if (tab->size == tab->alloced)
        {
          bfd_size_type amt = sizeof (struct elf_strtab_hash_entry *);
          tab->alloced *= 2;
          tab->array = (struct elf_strtab_hash_entry **)
-                      bfd_realloc (tab->array, tab->alloced * amt);
+             bfd_realloc_or_free (tab->array, tab->alloced * amt);
          if (tab->array == NULL)
          if (tab->array == NULL)
-           return (bfd_size_type) -1;
+           return (size_t) -1;
        }
 
       entry->u.index = tab->size++;
        }
 
       entry->u.index = tab->size++;
@@ -185,11 +180,9 @@ _bfd_elf_strtab_add (tab, str, copy)
 }
 
 void
 }
 
 void
-_bfd_elf_strtab_addref (tab, idx)
-     struct elf_strtab_hash *tab;
-     bfd_size_type idx;
+_bfd_elf_strtab_addref (struct elf_strtab_hash *tab, size_t idx)
 {
 {
-  if (idx == 0 || idx == (bfd_size_type) -1)
+  if (idx == 0 || idx == (size_t) -1)
     return;
   BFD_ASSERT (tab->sec_size == 0);
   BFD_ASSERT (idx < tab->size);
     return;
   BFD_ASSERT (tab->sec_size == 0);
   BFD_ASSERT (idx < tab->size);
@@ -197,11 +190,9 @@ _bfd_elf_strtab_addref (tab, idx)
 }
 
 void
 }
 
 void
-_bfd_elf_strtab_delref (tab, idx)
-     struct elf_strtab_hash *tab;
-     bfd_size_type idx;
+_bfd_elf_strtab_delref (struct elf_strtab_hash *tab, size_t idx)
 {
 {
-  if (idx == 0 || idx == (bfd_size_type) -1)
+  if (idx == 0 || idx == (size_t) -1)
     return;
   BFD_ASSERT (tab->sec_size == 0);
   BFD_ASSERT (idx < tab->size);
     return;
   BFD_ASSERT (tab->sec_size == 0);
   BFD_ASSERT (idx < tab->size);
@@ -209,27 +200,87 @@ _bfd_elf_strtab_delref (tab, idx)
   --tab->array[idx]->refcount;
 }
 
   --tab->array[idx]->refcount;
 }
 
+unsigned int
+_bfd_elf_strtab_refcount (struct elf_strtab_hash *tab, size_t idx)
+{
+  return tab->array[idx]->refcount;
+}
+
 void
 void
-_bfd_elf_strtab_clear_all_refs (tab)
-     struct elf_strtab_hash *tab;
+_bfd_elf_strtab_clear_all_refs (struct elf_strtab_hash *tab)
 {
 {
-  bfd_size_type idx;
+  size_t idx;
 
 
-  for (idx = 1; idx < tab->size; ++idx)
+  for (idx = 1; idx < tab->size; idx++)
     tab->array[idx]->refcount = 0;
 }
 
     tab->array[idx]->refcount = 0;
 }
 
+/* Save strtab refcounts prior to adding --as-needed library.  */
+
+struct strtab_save
+{
+  size_t size;
+  unsigned int refcount[1];
+};
+
+void *
+_bfd_elf_strtab_save (struct elf_strtab_hash *tab)
+{
+  struct strtab_save *save;
+  size_t idx, size;
+
+  size = sizeof (*save) + (tab->size - 1) * sizeof (save->refcount[0]);
+  save = bfd_malloc (size);
+  if (save == NULL)
+    return save;
+
+  save->size = tab->size;
+  for (idx = 1; idx < tab->size; idx++)
+    save->refcount[idx] = tab->array[idx]->refcount;
+  return save;
+}
+
+/* Restore strtab refcounts on finding --as-needed library not needed.  */
+
+void
+_bfd_elf_strtab_restore (struct elf_strtab_hash *tab, void *buf)
+{
+  size_t idx, curr_size = tab->size, save_size;
+  struct strtab_save *save = (struct strtab_save *) buf;
+
+  BFD_ASSERT (tab->sec_size == 0);
+  save_size = 1;
+  if (save != NULL)
+    save_size = save->size;
+  BFD_ASSERT (save_size <= curr_size);
+  tab->size = save_size;
+  for (idx = 1; idx < save_size; ++idx)
+    tab->array[idx]->refcount = save->refcount[idx];
+
+  for (; idx < curr_size; ++idx)
+    {
+      /* We don't remove entries from the hash table, just set their
+        REFCOUNT to zero.  Setting LEN zero will result in the size
+        growing if the entry is added again.  See _bfd_elf_strtab_add.  */
+      tab->array[idx]->refcount = 0;
+      tab->array[idx]->len = 0;
+    }
+}
+
 bfd_size_type
 bfd_size_type
-_bfd_elf_strtab_size (tab)
-     struct elf_strtab_hash *tab;
+_bfd_elf_strtab_size (struct elf_strtab_hash *tab)
 {
   return tab->sec_size ? tab->sec_size : tab->size;
 }
 
 bfd_size_type
 {
   return tab->sec_size ? tab->sec_size : tab->size;
 }
 
 bfd_size_type
-_bfd_elf_strtab_offset (tab, idx)
-     struct elf_strtab_hash *tab;
-     bfd_size_type idx;
+_bfd_elf_strtab_len (struct elf_strtab_hash *tab)
+{
+  return tab->size;
+}
+
+bfd_size_type
+_bfd_elf_strtab_offset (struct elf_strtab_hash *tab, size_t idx)
 {
   struct elf_strtab_hash_entry *entry;
 
 {
   struct elf_strtab_hash_entry *entry;
 
@@ -243,12 +294,24 @@ _bfd_elf_strtab_offset (tab, idx)
   return tab->array[idx]->u.index;
 }
 
   return tab->array[idx]->u.index;
 }
 
+const char *
+_bfd_elf_strtab_str (struct elf_strtab_hash *tab, size_t idx,
+                    bfd_size_type *offset)
+{
+  if (idx == 0)
+    return 0;
+  BFD_ASSERT (idx < tab->size);
+  BFD_ASSERT (tab->sec_size);
+  if (offset)
+    *offset = tab->array[idx]->u.index;
+  return tab->array[idx]->root.string;
+}
+
 bfd_boolean
 bfd_boolean
-_bfd_elf_strtab_emit (abfd, tab)
-     register bfd *abfd;
-     struct elf_strtab_hash *tab;
+_bfd_elf_strtab_emit (register bfd *abfd, struct elf_strtab_hash *tab)
 {
 {
-  bfd_size_type off = 1, i;
+  bfd_size_type off = 1;
+  size_t i;
 
   if (bfd_bwrite ("", 1, abfd) != 1)
     return FALSE;
 
   if (bfd_bwrite ("", 1, abfd) != 1)
     return FALSE;
@@ -256,15 +319,15 @@ _bfd_elf_strtab_emit (abfd, tab)
   for (i = 1; i < tab->size; ++i)
     {
       register const char *str;
   for (i = 1; i < tab->size; ++i)
     {
       register const char *str;
-      register size_t len;
+      register unsigned int len;
 
 
-      str = tab->array[i]->root.string;
-      len = tab->array[i]->len;
       BFD_ASSERT (tab->array[i]->refcount == 0);
       BFD_ASSERT (tab->array[i]->refcount == 0);
-      if (len == 0)
+      len = tab->array[i]->len;
+      if ((int) len < 0)
        continue;
 
        continue;
 
-      if (bfd_bwrite ((PTR) str, (bfd_size_type) len, abfd) != len)
+      str = tab->array[i]->root.string;
+      if (bfd_bwrite (str, len, abfd) != len)
        return FALSE;
 
       off += len;
        return FALSE;
 
       off += len;
@@ -274,177 +337,134 @@ _bfd_elf_strtab_emit (abfd, tab)
   return TRUE;
 }
 
   return TRUE;
 }
 
-/* Compare two elf_strtab_hash_entry structures.  This is called via qsort.  */
+/* Compare two elf_strtab_hash_entry structures.  Called via qsort.
+   Won't ever return zero as all entries differ, so there is no issue
+   with qsort stability here.  */
 
 static int
 
 static int
-cmplengthentry (a, b)
-     const PTR a;
-     const PTR b;
+strrevcmp (const void *a, const void *b)
 {
 {
-  struct elf_strtab_hash_entry * A = *(struct elf_strtab_hash_entry **) a;
-  struct elf_strtab_hash_entry * B = *(struct elf_strtab_hash_entry **) b;
-
-  if (A->len < B->len)
-    return 1;
-  else if (A->len > B->len)
-    return -1;
-
-  return memcmp (A->root.string, B->root.string, A->len);
+  struct elf_strtab_hash_entry *A = *(struct elf_strtab_hash_entry **) a;
+  struct elf_strtab_hash_entry *B = *(struct elf_strtab_hash_entry **) b;
+  unsigned int lenA = A->len;
+  unsigned int lenB = B->len;
+  const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1;
+  const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1;
+  int l = lenA < lenB ? lenA : lenB;
+
+  while (l)
+    {
+      if (*s != *t)
+       return (int) *s - (int) *t;
+      s--;
+      t--;
+      l--;
+    }
+  return lenA - lenB;
 }
 
 }
 
-static int
-last4_eq (a, b)
-     const PTR a;
-     const PTR b;
+static inline int
+is_suffix (const struct elf_strtab_hash_entry *A,
+          const struct elf_strtab_hash_entry *B)
 {
 {
-  struct elf_strtab_hash_entry * A = (struct elf_strtab_hash_entry *) a;
-  struct elf_strtab_hash_entry * B = (struct elf_strtab_hash_entry *) b;
-
-  if (memcmp (A->root.string + A->len - 5, B->root.string + B->len - 5, 4)
-      != 0)
-    /* This was a hashtable collision.  */
-    return 0;
-
   if (A->len <= B->len)
     /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
        not to be equal by the hash table.  */
     return 0;
 
   return memcmp (A->root.string + (A->len - B->len),
   if (A->len <= B->len)
     /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
        not to be equal by the hash table.  */
     return 0;
 
   return memcmp (A->root.string + (A->len - B->len),
-                B->root.string, B->len - 5) == 0;
+                B->root.string, B->len - 1) == 0;
 }
 
 /* This function assigns final string table offsets for used strings,
    merging strings matching suffixes of longer strings if possible.  */
 
 void
 }
 
 /* This function assigns final string table offsets for used strings,
    merging strings matching suffixes of longer strings if possible.  */
 
 void
-_bfd_elf_strtab_finalize (tab)
-     struct elf_strtab_hash *tab;
+_bfd_elf_strtab_finalize (struct elf_strtab_hash *tab)
 {
 {
-  struct elf_strtab_hash_entry **array, **a, **end, *e;
-  htab_t last4tab = NULL;
-  bfd_size_type size, amt;
-  struct elf_strtab_hash_entry *last[256], **last_ptr[256];
-
-  /* GCC 2.91.66 (egcs-1.1.2) on i386 miscompiles this function when i is
-     a 64-bit bfd_size_type: a 64-bit target or --enable-64-bit-bfd.
-     Besides, indexing with a long long wouldn't give anything but extra
-     cycles.  */
-  size_t i;
+  struct elf_strtab_hash_entry **array, **a, *e;
+  bfd_size_type amt, sec_size;
+  size_t size, i;
 
 
-  /* Now sort the strings by length, longest first.  */
-  array = NULL;
-  amt = tab->size * sizeof (struct elf_strtab_hash_entry *);
+  /* Sort the strings by suffix and length.  */
+  amt = tab->size;
+  amt *= sizeof (struct elf_strtab_hash_entry *);
   array = (struct elf_strtab_hash_entry **) bfd_malloc (amt);
   if (array == NULL)
     goto alloc_failure;
 
   array = (struct elf_strtab_hash_entry **) bfd_malloc (amt);
   if (array == NULL)
     goto alloc_failure;
 
-  memset (last, 0, sizeof (last));
-  for (i = 0; i < 256; ++i)
-    last_ptr[i] = &last[i];
   for (i = 1, a = array; i < tab->size; ++i)
   for (i = 1, a = array; i < tab->size; ++i)
-    if (tab->array[i]->refcount)
-      *a++ = tab->array[i];
-    else
-      tab->array[i]->len = 0;
+    {
+      e = tab->array[i];
+      if (e->refcount)
+       {
+         *a++ = e;
+         /* Adjust the length to not include the zero terminator.  */
+         e->len -= 1;
+       }
+      else
+       e->len = 0;
+    }
 
   size = a - array;
 
   size = a - array;
+  if (size != 0)
+    {
+      qsort (array, size, sizeof (struct elf_strtab_hash_entry *), strrevcmp);
 
 
-  qsort (array, size, sizeof (struct elf_strtab_hash_entry *), cmplengthentry);
+      /* Loop over the sorted array and merge suffixes.  Start from the
+        end because we want eg.
 
 
-  last4tab = htab_create_alloc (size * 4, NULL, last4_eq, NULL, calloc, free);
-  if (last4tab == NULL)
-    goto alloc_failure;
+        s1 -> "d"
+        s2 -> "bcd"
+        s3 -> "abcd"
 
 
-  /* Now insert the strings into hash tables (strings with last 4 characters
-     and strings with last character equal), look for longer strings which
-     we're suffix of.  */
-  for (a = array, end = array + size; a < end; a++)
-    {
-      register hashval_t hash;
-      unsigned int c;
-      unsigned int j;
-      const unsigned char *s;
-      PTR *p;
-
-      e = *a;
-      if (e->len > 4)
-       {
-         s = e->root.string + e->len - 1;
-         hash = 0;
-         for (j = 0; j < 4; j++)
-           {
-             c = *--s;
-             hash += c + (c << 17);
-             hash ^= hash >> 2;
-           }
-         p = htab_find_slot_with_hash (last4tab, e, hash, INSERT);
-         if (p == NULL)
-           goto alloc_failure;
-         if (*p)
-           {
-             struct elf_strtab_hash_entry *ent;
+        to end up as
 
 
-             ent = (struct elf_strtab_hash_entry *) *p;
-             e->u.suffix = ent;
-             e->len = 0;
-             continue;
-           }
-         else
-           *p = (PTR) e;
-       }
-      else
-       {
-         struct elf_strtab_hash_entry *tem;
+        s3 -> "abcd"
+        s2 _____^
+        s1 _______^
 
 
-         c = e->root.string[e->len - 2] & 0xff;
+        ie. we don't want s1 pointing into the old s2.  */
+      e = *--a;
+      e->len += 1;
+      while (--a >= array)
+       {
+         struct elf_strtab_hash_entry *cmp = *a;
 
 
-         for (tem = last[c]; tem; tem = tem->u.next)
-           if (tem->len > e->len
-               && memcmp (tem->root.string + (tem->len - e->len),
-                          e->root.string, e->len - 1) == 0)
-             break;
-         if (tem)
+         cmp->len += 1;
+         if (is_suffix (e, cmp))
            {
            {
-             e->u.suffix = tem;
-             e->len = 0;
-             continue;
+             cmp->u.suffix = e;
+             cmp->len = -cmp->len;
            }
            }
+         else
+           e = cmp;
        }
        }
-
-      c = e->root.string[e->len - 2] & 0xff;
-      /* Put longest strings first.  */
-      *last_ptr[c] = e;
-      last_ptr[c] = &e->u.next;
-      e->u.next = NULL;
     }
 
     }
 
-alloc_failure:
+ alloc_failure:
   if (array)
     free (array);
   if (array)
     free (array);
-  if (last4tab)
-    htab_delete (last4tab);
 
 
-  /* Now assign positions to the strings we want to keep.  */
-  size = 1;
+  /* Assign positions to the strings we want to keep.  */
+  sec_size = 1;
   for (i = 1; i < tab->size; ++i)
     {
       e = tab->array[i];
   for (i = 1; i < tab->size; ++i)
     {
       e = tab->array[i];
-      if (e->refcount && e->len)
+      if (e->refcount && e->len > 0)
        {
        {
-         e->u.index = size;
-         size += e->len;
+         e->u.index = sec_size;
+         sec_size += e->len;
        }
     }
 
        }
     }
 
-  tab->sec_size = size;
+  tab->sec_size = sec_size;
 
 
-  /* And now adjust the rest.  */
+  /* Adjust the rest.  */
   for (i = 1; i < tab->size; ++i)
     {
       e = tab->array[i];
   for (i = 1; i < tab->size; ++i)
     {
       e = tab->array[i];
-      if (e->refcount && ! e->len)
-       e->u.index = e->u.suffix->u.index
-                    + (e->u.suffix->len - strlen (e->root.string) - 1);
+      if (e->refcount && e->len < 0)
+       e->u.index = e->u.suffix->u.index + (e->u.suffix->len + e->len);
     }
 }
     }
 }
This page took 0.046219 seconds and 4 git commands to generate.