]> git.gag.com Git - fw/sdcc/blobdiff - support/cpp/libcpp/symtab.c
* support/cpp/output.h, support/cpp/opts-common.c,
[fw/sdcc] / support / cpp / libcpp / symtab.c
index ffa28f5f7a5e853cf60cf9d0475f3a32c6c54c40..f2a918a719b1226ff6273c96d29da6ba80cde481 100644 (file)
@@ -1,9 +1,10 @@
 /* Hash tables.
 /* Hash tables.
-   Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2003, 2004, 2008, 2009
+   Free Software Foundation, Inc.
 
 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
 
 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, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
 
 This program is distributed in the hope that it will be useful,
 later version.
 
 This program is distributed in the hope that it will be useful,
@@ -12,8 +13,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+along with this program; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.
 
  In other words, you are welcome to use, share and improve this program.
  You are forbidden to forbid anyone else to use, share and improve
 
  In other words, you are welcome to use, share and improve this program.
  You are forbidden to forbid anyone else to use, share and improve
@@ -27,13 +28,15 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    hash tables (see libiberty/hashtab.c).  The abstraction penalty was
    too high to continue using the generic form.  This code knows
    intrinsically how to calculate a hash value, and how to compare an
    hash tables (see libiberty/hashtab.c).  The abstraction penalty was
    too high to continue using the generic form.  This code knows
    intrinsically how to calculate a hash value, and how to compare an
-   existing entry with a potential new one.  Also, the ability to
-   delete members from the table has been removed.  */
+   existing entry with a potential new one.  */
 
 static unsigned int calc_hash (const unsigned char *, size_t);
 static void ht_expand (hash_table *);
 static double approx_sqrt (double);
 
 
 static unsigned int calc_hash (const unsigned char *, size_t);
 static void ht_expand (hash_table *);
 static double approx_sqrt (double);
 
+/* A deleted entry.  */
+#define DELETED ((hashnode) -1)
+
 /* Calculate the hash of the string STR of length LEN.  */
 
 static unsigned int
 /* Calculate the hash of the string STR of length LEN.  */
 
 static unsigned int
@@ -60,8 +63,8 @@ ht_create (unsigned int order)
 
   /* Strings need no alignment.  */
   _obstack_begin (&table->stack, 0, 0,
 
   /* Strings need no alignment.  */
   _obstack_begin (&table->stack, 0, 0,
-                 (void *(*) (long)) xmalloc,
-                 (void (*) (void *)) free);
+                  (void *(*) (long)) xmalloc,
+                  (void (*) (void *)) free);
 
   obstack_alignment_mask (&table->stack) = 0;
 
 
   obstack_alignment_mask (&table->stack) = 0;
 
@@ -83,28 +86,26 @@ ht_destroy (hash_table *table)
 }
 
 /* Returns the hash entry for the a STR of length LEN.  If that string
 }
 
 /* Returns the hash entry for the a STR of length LEN.  If that string
-   already exists in the table, returns the existing entry, and, if
-   INSERT is CPP_ALLOCED, frees the last obstack object.  If the
+   already exists in the table, returns the existing entry.  If the
    identifier hasn't been seen before, and INSERT is CPP_NO_INSERT,
    returns NULL.  Otherwise insert and returns a new entry.  A new
    identifier hasn't been seen before, and INSERT is CPP_NO_INSERT,
    returns NULL.  Otherwise insert and returns a new entry.  A new
-   string is alloced if INSERT is CPP_ALLOC, otherwise INSERT is
-   CPP_ALLOCED and the item is assumed to be at the top of the
-   obstack.  */
+   string is allocated.  */
 hashnode
 ht_lookup (hash_table *table, const unsigned char *str, size_t len,
 hashnode
 ht_lookup (hash_table *table, const unsigned char *str, size_t len,
-          enum ht_lookup_option insert)
+           enum ht_lookup_option insert)
 {
   return ht_lookup_with_hash (table, str, len, calc_hash (str, len),
 {
   return ht_lookup_with_hash (table, str, len, calc_hash (str, len),
-                             insert);
+                              insert);
 }
 
 hashnode
 ht_lookup_with_hash (hash_table *table, const unsigned char *str,
 }
 
 hashnode
 ht_lookup_with_hash (hash_table *table, const unsigned char *str,
-                    size_t len, unsigned int hash,
-                    enum ht_lookup_option insert)
+                     size_t len, unsigned int hash,
+                     enum ht_lookup_option insert)
 {
   unsigned int hash2;
   unsigned int index;
 {
   unsigned int hash2;
   unsigned int index;
+  unsigned int deleted_index = table->nslots;
   size_t sizemask;
   hashnode node;
 
   size_t sizemask;
   hashnode node;
 
@@ -113,58 +114,63 @@ ht_lookup_with_hash (hash_table *table, const unsigned char *str,
   table->searches++;
 
   node = table->entries[index];
   table->searches++;
 
   node = table->entries[index];
+
   if (node != NULL)
     {
   if (node != NULL)
     {
-      if (node->hash_value == hash
-         && HT_LEN (node) == (unsigned int) len
-         && !memcmp (HT_STR (node), str, len))
-       {
-         if (insert == HT_ALLOCED)
-           /* The string we search for was placed at the end of the
-              obstack.  Release it.  */
-           obstack_free (&table->stack, (void *) str);
-         return node;
-       }
+      if (node == DELETED)
+        deleted_index = index;
+      else if (node->hash_value == hash
+               && HT_LEN (node) == (unsigned int) len
+               && !memcmp (HT_STR (node), str, len))
+        return node;
 
       /* hash2 must be odd, so we're guaranteed to visit every possible
 
       /* hash2 must be odd, so we're guaranteed to visit every possible
-        location in the table during rehashing.  */
+         location in the table during rehashing.  */
       hash2 = ((hash * 17) & sizemask) | 1;
 
       for (;;)
       hash2 = ((hash * 17) & sizemask) | 1;
 
       for (;;)
-       {
-         table->collisions++;
-         index = (index + hash2) & sizemask;
-         node = table->entries[index];
-         if (node == NULL)
-           break;
-
-         if (node->hash_value == hash
-             && HT_LEN (node) == (unsigned int) len
-             && !memcmp (HT_STR (node), str, len))
-           {
-             if (insert == HT_ALLOCED)
-             /* The string we search for was placed at the end of the
-                obstack.  Release it.  */
-               obstack_free (&table->stack, (void *) str);
-             return node;
-           }
-       }
+        {
+          table->collisions++;
+          index = (index + hash2) & sizemask;
+          node = table->entries[index];
+          if (node == NULL)
+            break;
+
+          if (node == DELETED)
+            {
+              if (deleted_index != table->nslots)
+                deleted_index = index;
+            }
+          else if (node->hash_value == hash
+                   && HT_LEN (node) == (unsigned int) len
+                   && !memcmp (HT_STR (node), str, len))
+            return node;
+        }
     }
 
   if (insert == HT_NO_INSERT)
     return NULL;
 
     }
 
   if (insert == HT_NO_INSERT)
     return NULL;
 
+  /* We prefer to overwrite the first deleted slot we saw.  */
+  if (deleted_index != table->nslots)
+    index = deleted_index;
+
   node = (*table->alloc_node) (table);
   table->entries[index] = node;
 
   HT_LEN (node) = (unsigned int) len;
   node->hash_value = hash;
   node = (*table->alloc_node) (table);
   table->entries[index] = node;
 
   HT_LEN (node) = (unsigned int) len;
   node->hash_value = hash;
-  if (insert == HT_ALLOC)
+
+  if (table->alloc_subobject)
+    {
+      char *chars = table->alloc_subobject (len + 1);
+      memcpy (chars, str, len);
+      chars[len] = '\0';
+      HT_STR (node) = (const unsigned char *) chars;
+    }
+  else
     HT_STR (node) = (const unsigned char *) obstack_copy0 (&table->stack,
                                                            str, len);
     HT_STR (node) = (const unsigned char *) obstack_copy0 (&table->stack,
                                                            str, len);
-  else
-    HT_STR (node) = str;
 
   if (++table->nelements * 4 >= table->nslots * 3)
     /* Must expand the string table.  */
 
   if (++table->nelements * 4 >= table->nslots * 3)
     /* Must expand the string table.  */
@@ -188,23 +194,23 @@ ht_expand (hash_table *table)
   p = table->entries;
   limit = p + table->nslots;
   do
   p = table->entries;
   limit = p + table->nslots;
   do
-    if (*p)
+    if (*p && *p != DELETED)
       {
       {
-       unsigned int index, hash, hash2;
-
-       hash = (*p)->hash_value;
-       index = hash & sizemask;
-
-       if (nentries[index])
-         {
-           hash2 = ((hash * 17) & sizemask) | 1;
-           do
-             {
-               index = (index + hash2) & sizemask;
-             }
-           while (nentries[index]);
-         }
-       nentries[index] = *p;
+        unsigned int index, hash, hash2;
+
+        hash = (*p)->hash_value;
+        index = hash & sizemask;
+
+        if (nentries[index])
+          {
+            hash2 = ((hash * 17) & sizemask) | 1;
+            do
+              {
+                index = (index + hash2) & sizemask;
+              }
+            while (nentries[index]);
+          }
+        nentries[index] = *p;
       }
   while (++p < limit);
 
       }
   while (++p < limit);
 
@@ -225,10 +231,28 @@ ht_forall (hash_table *table, ht_cb cb, const void *v)
   p = table->entries;
   limit = p + table->nslots;
   do
   p = table->entries;
   limit = p + table->nslots;
   do
-    if (*p)
+    if (*p && *p != DELETED)
+      {
+        if ((*cb) (table->pfile, *p, v) == 0)
+          break;
+      }
+  while (++p < limit);
+}
+
+/* Like ht_forall, but a nonzero return from the callback means that
+   the entry should be removed from the table.  */
+void
+ht_purge (hash_table *table, ht_cb cb, const void *v)
+{
+  hashnode *p, *limit;
+
+  p = table->entries;
+  limit = p + table->nslots;
+  do
+    if (*p && *p != DELETED)
       {
       {
-       if ((*cb) (table->pfile, *p, v) == 0)
-         break;
+        if ((*cb) (table->pfile, *p, v))
+          *p = DELETED;
       }
   while (++p < limit);
 }
       }
   while (++p < limit);
 }
@@ -236,8 +260,8 @@ ht_forall (hash_table *table, ht_cb cb, const void *v)
 /* Restore the hash table.  */
 void
 ht_load (hash_table *ht, hashnode *entries,
 /* Restore the hash table.  */
 void
 ht_load (hash_table *ht, hashnode *entries,
-        unsigned int nslots, unsigned int nelements,
-        bool own)
+         unsigned int nslots, unsigned int nelements,
+         bool own)
 {
   if (ht->entries_owned)
     free (ht->entries);
 {
   if (ht->entries_owned)
     free (ht->entries);
@@ -253,30 +277,32 @@ void
 ht_dump_statistics (hash_table *table)
 {
   size_t nelts, nids, overhead, headers;
 ht_dump_statistics (hash_table *table)
 {
   size_t nelts, nids, overhead, headers;
-  size_t total_bytes, longest;
+  size_t total_bytes, longest, deleted = 0;
   double sum_of_squares, exp_len, exp_len2, exp2_len;
   hashnode *p, *limit;
 
 #define SCALE(x) ((unsigned long) ((x) < 1024*10 \
   double sum_of_squares, exp_len, exp_len2, exp2_len;
   hashnode *p, *limit;
 
 #define SCALE(x) ((unsigned long) ((x) < 1024*10 \
-                 ? (x) \
-                 : ((x) < 1024*1024*10 \
-                    ? (x) / 1024 \
-                    : (x) / (1024*1024))))
+                  ? (x) \
+                  : ((x) < 1024*1024*10 \
+                     ? (x) / 1024 \
+                     : (x) / (1024*1024))))
 #define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
 
   total_bytes = longest = sum_of_squares = nids = 0;
   p = table->entries;
   limit = p + table->nslots;
   do
 #define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
 
   total_bytes = longest = sum_of_squares = nids = 0;
   p = table->entries;
   limit = p + table->nslots;
   do
-    if (*p)
+    if (*p == DELETED)
+      ++deleted;
+    else if (*p)
       {
       {
-       size_t n = HT_LEN (*p);
+        size_t n = HT_LEN (*p);
 
 
-       total_bytes += n;
-       sum_of_squares += (double) n * n;
-       if (n > longest)
-         longest = n;
-       nids++;
+        total_bytes += n;
+        sum_of_squares += (double) n * n;
+        if (n > longest)
+          longest = n;
+        nids++;
       }
   while (++p < limit);
 
       }
   while (++p < limit);
 
@@ -285,29 +311,31 @@ ht_dump_statistics (hash_table *table)
   headers = table->nslots * sizeof (hashnode);
 
   fprintf (stderr, "\nString pool\nentries\t\t%lu\n",
   headers = table->nslots * sizeof (hashnode);
 
   fprintf (stderr, "\nString pool\nentries\t\t%lu\n",
-          (unsigned long) nelts);
+           (unsigned long) nelts);
   fprintf (stderr, "identifiers\t%lu (%.2f%%)\n",
   fprintf (stderr, "identifiers\t%lu (%.2f%%)\n",
-          (unsigned long) nids, nids * 100.0 / nelts);
+           (unsigned long) nids, nids * 100.0 / nelts);
   fprintf (stderr, "slots\t\t%lu\n",
   fprintf (stderr, "slots\t\t%lu\n",
-          (unsigned long) table->nslots);
+           (unsigned long) table->nslots);
+  fprintf (stderr, "deleted\t\t%lu\n",
+           (unsigned long) deleted);
   fprintf (stderr, "bytes\t\t%lu%c (%lu%c overhead)\n",
   fprintf (stderr, "bytes\t\t%lu%c (%lu%c overhead)\n",
-          SCALE (total_bytes), LABEL (total_bytes),
-          SCALE (overhead), LABEL (overhead));
+           SCALE (total_bytes), LABEL (total_bytes),
+           SCALE (overhead), LABEL (overhead));
   fprintf (stderr, "table size\t%lu%c\n",
   fprintf (stderr, "table size\t%lu%c\n",
-          SCALE (headers), LABEL (headers));
+           SCALE (headers), LABEL (headers));
 
   exp_len = (double)total_bytes / (double)nelts;
   exp2_len = exp_len * exp_len;
   exp_len2 = (double) sum_of_squares / (double) nelts;
 
   fprintf (stderr, "coll/search\t%.4f\n",
 
   exp_len = (double)total_bytes / (double)nelts;
   exp2_len = exp_len * exp_len;
   exp_len2 = (double) sum_of_squares / (double) nelts;
 
   fprintf (stderr, "coll/search\t%.4f\n",
-          (double) table->collisions / (double) table->searches);
+           (double) table->collisions / (double) table->searches);
   fprintf (stderr, "ins/search\t%.4f\n",
   fprintf (stderr, "ins/search\t%.4f\n",
-          (double) nelts / (double) table->searches);
+           (double) nelts / (double) table->searches);
   fprintf (stderr, "avg. entry\t%.2f bytes (+/- %.2f)\n",
   fprintf (stderr, "avg. entry\t%.2f bytes (+/- %.2f)\n",
-          exp_len, approx_sqrt (exp_len2 - exp2_len));
+           exp_len, approx_sqrt (exp_len2 - exp2_len));
   fprintf (stderr, "longest entry\t%lu\n",
   fprintf (stderr, "longest entry\t%lu\n",
-          (unsigned long) longest);
+           (unsigned long) longest);
 #undef SCALE
 #undef LABEL
 }
 #undef SCALE
 #undef LABEL
 }