]> git.saurik.com Git - bison.git/blobdiff - lib/abitset.c
ChangeLog (2006-09-15): add Odd Arild Olsen's role for push.c.
[bison.git] / lib / abitset.c
index 9cdb40ce8752dfb4cd2af612d0593e95acba2be7..dc71713db0ae06175f495d48a5ce66cd2f68f978 100644 (file)
@@ -1,10 +1,11 @@
 /* Array bitsets.
 /* Array bitsets.
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002-2003, 2006, 2009-2010 Free Software Foundation,
+   Inc.
    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
 
    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
 
-   This program is free software; you can redistribute it and/or modify
+   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
    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,
    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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
-*/
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include <config.h>
 
 #include "abitset.h"
 
 #include "abitset.h"
+#include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 
 /* This file implements fixed size bitsets stored as an array
    of words.  Any unused bits in the last word must be zero.  */
 
 #include <stdlib.h>
 #include <string.h>
 
 /* This file implements fixed size bitsets stored as an array
    of words.  Any unused bits in the last word must be zero.  */
 
-typedef struct abitset_struct
-{
-  unsigned int n_bits; /* Number of bits.  */
-  bitset_word words[1];        /* The array of bits.  */
-}
-*abitset;
-
-
-struct bitset_struct
-{
-  struct bbitset_struct b;
-  struct abitset_struct a;
-};
-
-static void abitset_unused_clear PARAMS ((bitset));
-
-static int abitset_small_list PARAMS ((bitset, bitset_bindex *, bitset_bindex,
-                                      bitset_bindex *));
-
-static void abitset_set PARAMS ((bitset, bitset_bindex));
-static void abitset_reset PARAMS ((bitset, bitset_bindex));
-static int abitset_test PARAMS ((bitset, bitset_bindex));
-static int abitset_size PARAMS ((bitset));
-static int abitset_op1 PARAMS ((bitset, enum bitset_ops));
-static int abitset_op2 PARAMS ((bitset, bitset, enum bitset_ops));
-static int abitset_op3 PARAMS ((bitset, bitset, bitset, enum bitset_ops));
-static int abitset_op4 PARAMS ((bitset, bitset, bitset, bitset,
-                               enum bitset_ops));
-static int abitset_list PARAMS ((bitset, bitset_bindex *, bitset_bindex,
-                                bitset_bindex *));
-static int abitset_reverse_list
-PARAMS ((bitset, bitset_bindex *, bitset_bindex, bitset_bindex *));
-
 #define ABITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
 #define ABITSET_WORDS(X) ((X)->a.words)
 #define ABITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
 #define ABITSET_WORDS(X) ((X)->a.words)
-#define ABITSET_N_BITS(X) ((X)->a.n_bits)
 
 
 
 
-/* Return size in bits of bitset SRC.  */
-static int
-abitset_size (src)
-     bitset src;
+static bitset_bindex
+abitset_resize (bitset src, bitset_bindex size)
 {
 {
-  return ABITSET_N_BITS (src);
-}
+    /* These bitsets have a fixed size.  */
+    if (BITSET_SIZE_ (src) != size)
+      abort ();
 
 
+    return size;
+}
 
 /* Find list of up to NUM bits set in BSET starting from and including
  *NEXT and store in array LIST.  Return with actual number of bits
  found and with *NEXT indicating where search stopped.  */
 
 /* Find list of up to NUM bits set in BSET starting from and including
  *NEXT and store in array LIST.  Return with actual number of bits
  found and with *NEXT indicating where search stopped.  */
-static int
-abitset_small_list (src, list, num, next)
-     bitset src;
-     bitset_bindex *list;
-     bitset_bindex num;
-     bitset_bindex *next;
+static bitset_bindex
+abitset_small_list (bitset src, bitset_bindex *list,
+                   bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex bitno;
   bitset_bindex count;
 {
   bitset_bindex bitno;
   bitset_bindex count;
@@ -96,7 +58,7 @@ abitset_small_list (src, list, num, next)
   if (!word)
     return 0;
 
   if (!word)
     return 0;
 
-  size = ABITSET_N_BITS (src);
+  size = BITSET_SIZE_ (src);
   bitno = *next;
   if (bitno >= size)
     return 0;
   bitno = *next;
   if (bitno >= size)
     return 0;
@@ -139,35 +101,34 @@ abitset_small_list (src, list, num, next)
 
 /* Set bit BITNO in bitset DST.  */
 static void
 
 /* Set bit BITNO in bitset DST.  */
 static void
-abitset_set (dst, bitno)
-     bitset dst ATTRIBUTE_UNUSED;
-     bitset_bindex bitno ATTRIBUTE_UNUSED;
+abitset_set (bitset dst ATTRIBUTE_UNUSED, bitset_bindex bitno ATTRIBUTE_UNUSED)
 {
 {
-  /* This should never occur for abitsets.  */
+  /* This should never occur for abitsets since we should always hit
+     the cache.  It is likely someone is trying to access outside the
+     bounds of the bitset.  */
   abort ();
 }
 
 
 /* Reset bit BITNO in bitset DST.  */
 static void
   abort ();
 }
 
 
 /* Reset bit BITNO in bitset DST.  */
 static void
-abitset_reset (dst, bitno)
-     bitset dst ATTRIBUTE_UNUSED;
-     bitset_bindex bitno ATTRIBUTE_UNUSED;
+abitset_reset (bitset dst ATTRIBUTE_UNUSED,
+              bitset_bindex bitno ATTRIBUTE_UNUSED)
 {
 {
-  /* This should never occur for abitsets.  */
-  abort ();
+  /* This should never occur for abitsets since we should always hit
+     the cache.  It is likely someone is trying to access outside the
+     bounds of the bitset.  Since the bit is zero anyway, let it pass.  */
 }
 
 
 /* Test bit BITNO in bitset SRC.  */
 }
 
 
 /* Test bit BITNO in bitset SRC.  */
-static int
-abitset_test (src, bitno)
-     bitset src ATTRIBUTE_UNUSED;
-     bitset_bindex bitno ATTRIBUTE_UNUSED;
+static bool
+abitset_test (bitset src ATTRIBUTE_UNUSED,
+             bitset_bindex bitno ATTRIBUTE_UNUSED)
 {
 {
-  /* This should never occur for abitsets.  */
-  abort ();
-  return 0;
+  /* This should never occur for abitsets since we should always
+     hit the cache.  */
+  return false;
 }
 
 
 }
 
 
@@ -175,12 +136,9 @@ abitset_test (src, bitno)
    from and including NEXT and store in array LIST.  Return with
    actual number of bits found and with *NEXT indicating where search
    stopped.  */
    from and including NEXT and store in array LIST.  Return with
    actual number of bits found and with *NEXT indicating where search
    stopped.  */
-static int
-abitset_reverse_list (src, list, num, next)
-     bitset src;
-     bitset_bindex *list;
-     bitset_bindex num;
-     bitset_bindex *next;
+static bitset_bindex
+abitset_list_reverse (bitset src, bitset_bindex *list,
+                     bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex bitno;
   bitset_bindex rbitno;
 {
   bitset_bindex bitno;
   bitset_bindex rbitno;
@@ -188,9 +146,8 @@ abitset_reverse_list (src, list, num, next)
   bitset_windex windex;
   unsigned int bitcnt;
   bitset_bindex bitoff;
   bitset_windex windex;
   unsigned int bitcnt;
   bitset_bindex bitoff;
-  bitset_word word;
   bitset_word *srcp = ABITSET_WORDS (src);
   bitset_word *srcp = ABITSET_WORDS (src);
-  bitset_bindex n_bits = ABITSET_N_BITS (src);
+  bitset_bindex n_bits = BITSET_SIZE_ (src);
 
   rbitno = *next;
 
 
   rbitno = *next;
 
@@ -208,9 +165,10 @@ abitset_reverse_list (src, list, num, next)
   bitcnt = bitno % BITSET_WORD_BITS;
   bitoff = windex * BITSET_WORD_BITS;
 
   bitcnt = bitno % BITSET_WORD_BITS;
   bitoff = windex * BITSET_WORD_BITS;
 
-  for (; windex != ~0U; windex--, bitoff -= BITSET_WORD_BITS,
-        bitcnt = BITSET_WORD_BITS - 1)
+  do
     {
     {
+      bitset_word word;
+
       word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt);
       for (; word; bitcnt--)
        {
       word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt);
       for (; word; bitcnt--)
        {
@@ -225,7 +183,10 @@ abitset_reverse_list (src, list, num, next)
            }
          word <<= 1;
        }
            }
          word <<= 1;
        }
+      bitoff -= BITSET_WORD_BITS;
+      bitcnt = BITSET_WORD_BITS - 1;
     }
     }
+  while (windex--);
 
   *next = n_bits - (bitoff + 1);
   return count;
 
   *next = n_bits - (bitoff + 1);
   return count;
@@ -235,12 +196,9 @@ abitset_reverse_list (src, list, num, next)
 /* Find list of up to NUM bits set in BSET starting from and including
  *NEXT and store in array LIST.  Return with actual number of bits
  found and with *NEXT indicating where search stopped.  */
 /* Find list of up to NUM bits set in BSET starting from and including
  *NEXT and store in array LIST.  Return with actual number of bits
  found and with *NEXT indicating where search stopped.  */
-static int
-abitset_list (src, list, num, next)
-     bitset src;
-     bitset_bindex *list;
-     bitset_bindex num;
-     bitset_bindex *next;
+static bitset_bindex
+abitset_list (bitset src, bitset_bindex *list,
+             bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex bitno;
   bitset_bindex count;
 {
   bitset_bindex bitno;
   bitset_bindex count;
@@ -268,7 +226,7 @@ abitset_list (src, list, num, next)
     }
   else
     {
     }
   else
     {
-      if (bitno >= ABITSET_N_BITS (src))
+      if (bitno >= BITSET_SIZE_ (src))
        return 0;
 
       windex = bitno / BITSET_WORD_BITS;
        return 0;
 
       windex = bitno / BITSET_WORD_BITS;
@@ -340,309 +298,526 @@ abitset_list (src, list, num, next)
 
 /* Ensure that any unused bits within the last word are clear.  */
 static inline void
 
 /* Ensure that any unused bits within the last word are clear.  */
 static inline void
-abitset_unused_clear (dst)
-     bitset dst;
+abitset_unused_clear (bitset dst)
 {
   unsigned int last_bit;
 
 {
   unsigned int last_bit;
 
-  last_bit = ABITSET_N_BITS (dst) % BITSET_WORD_BITS;
+  last_bit = BITSET_SIZE_ (dst) % BITSET_WORD_BITS;
   if (last_bit)
     ABITSET_WORDS (dst)[dst->b.csize - 1] &=
   if (last_bit)
     ABITSET_WORDS (dst)[dst->b.csize - 1] &=
-      (bitset_word) ((1 << last_bit) - 1);
+      ((bitset_word) 1 << last_bit) - 1;
 }
 
 
 }
 
 
-static int
-abitset_op1 (dst, op)
-     bitset dst;
-     enum bitset_ops op;
+static void
+abitset_ones (bitset dst)
 {
 {
-  unsigned int i;
   bitset_word *dstp = ABITSET_WORDS (dst);
   bitset_word *dstp = ABITSET_WORDS (dst);
-  unsigned int bytes;
+  size_t bytes;
 
   bytes = sizeof (bitset_word) * dst->b.csize;
 
 
   bytes = sizeof (bitset_word) * dst->b.csize;
 
-  switch (op)
-    {
-    case BITSET_OP_ZERO:
-      memset (dstp, 0, bytes);
-      break;
-
-    case BITSET_OP_ONES:
-      memset (dstp, ~0, bytes);
-      abitset_unused_clear (dst);
-      break;
-
-    case BITSET_OP_EMPTY_P:
-      for (i = 0; i < dst->b.csize; i++)
-       if (dstp[i])
-         return 0;
-      break;
-
-    default:
-      abort ();
-    }
+  memset (dstp, -1, bytes);
+  abitset_unused_clear (dst);
+}
+
+
+static void
+abitset_zero (bitset dst)
+{
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  size_t bytes;
+
+  bytes = sizeof (bitset_word) * dst->b.csize;
+
+  memset (dstp, 0, bytes);
+}
+
+
+static bool
+abitset_empty_p (bitset dst)
+{
+  bitset_windex i;
+  bitset_word *dstp = ABITSET_WORDS (dst);
+
+  for (i = 0; i < dst->b.csize; i++)
+    if (dstp[i])
+      return false;
+
+  return true;
+}
+
+
+static void
+abitset_copy1 (bitset dst, bitset src)
+{
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  if (srcp == dstp)
+      return;
+  memcpy (dstp, srcp, sizeof (bitset_word) * size);
+}
+
+
+static void
+abitset_not (bitset dst, bitset src)
+{
+  bitset_windex i;
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = ~(*srcp++);
+  abitset_unused_clear (dst);
+}
+
+
+static bool
+abitset_equal_p (bitset dst, bitset src)
+{
+  bitset_windex i;
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      if (*srcp++ != *dstp++)
+         return false;
+  return true;
+}
+
+
+static bool
+abitset_subset_p (bitset dst, bitset src)
+{
+  bitset_windex i;
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
 
 
-  return 1;
+  for (i = 0; i < size; i++, dstp++, srcp++)
+      if (*dstp != (*srcp | *dstp))
+         return false;
+  return true;
 }
 
 
 }
 
 
-static int
-abitset_op2 (dst, src, op)
-     bitset dst;
-     bitset src;
-     enum bitset_ops op;
+static bool
+abitset_disjoint_p (bitset dst, bitset src)
 {
 {
-  unsigned int i;
+  bitset_windex i;
   bitset_word *srcp = ABITSET_WORDS (src);
   bitset_word *dstp = ABITSET_WORDS (dst);
   bitset_windex size = dst->b.csize;
 
   bitset_word *srcp = ABITSET_WORDS (src);
   bitset_word *dstp = ABITSET_WORDS (dst);
   bitset_windex size = dst->b.csize;
 
-  switch (op)
+  for (i = 0; i < size; i++)
+      if (*srcp++ & *dstp++)
+         return false;
+
+  return true;
+}
+
+
+static void
+abitset_and (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = *src1p++ & *src2p++;
+}
+
+
+static bool
+abitset_and_cmp (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
     {
     {
-    case BITSET_OP_COPY:
-      if (srcp == dstp)
-       break;
-      memcpy (dstp, srcp, sizeof (bitset_word) * size);
-      break;
-
-    case BITSET_OP_NOT:
-      for (i = 0; i < size; i++)
-       *dstp++ = ~(*srcp++);
-      abitset_unused_clear (dst);
-      break;
-
-    case BITSET_OP_EQUAL_P:
-      for (i = 0; i < size; i++)
-       if (*srcp++ != *dstp++)
-         return 0;
-      break;
-      
-    case BITSET_OP_SUBSET_P:
-      for (i = 0; i < size; i++, dstp++, srcp++)
-       if (*dstp != (*srcp | *dstp))
-         return 0;
-      break;
-      
-    case BITSET_OP_DISJOINT_P:
-      for (i = 0; i < size; i++)
-       if (*srcp++ & *dstp++)
-         return 0;
-      break;
-      
-    default:
-      abort ();
+      bitset_word tmp = *src1p++ & *src2p++;
+
+      if (*dstp != tmp)
+       {
+         changed = true;
+         *dstp = tmp;
+       }
     }
     }
+  return changed;
+}
 
 
-  return 1;
+
+static void
+abitset_andn (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = *src1p++ & ~(*src2p++);
 }
 
 
 }
 
 
-static int
-abitset_op3 (dst, src1, src2, op)
-     bitset dst;
-     bitset src1;
-     bitset src2;
-     enum bitset_ops op;
+static bool
+abitset_andn_cmp (bitset dst, bitset src1, bitset src2)
 {
 {
-  unsigned int i;
-  int changed = 0;
+  bitset_windex i;
+  bool changed = false;
   bitset_word *src1p = ABITSET_WORDS (src1);
   bitset_word *src2p = ABITSET_WORDS (src2);
   bitset_word *dstp = ABITSET_WORDS (dst);
   bitset_windex size = dst->b.csize;
 
   bitset_word *src1p = ABITSET_WORDS (src1);
   bitset_word *src2p = ABITSET_WORDS (src2);
   bitset_word *dstp = ABITSET_WORDS (dst);
   bitset_windex size = dst->b.csize;
 
-  switch (op)
+  for (i = 0; i < size; i++, dstp++)
     {
     {
-    case BITSET_OP_OR:
-      for (i = 0; i < size; i++, dstp++)
-       {
-         bitset_word tmp = *src1p++ | *src2p++;
+      bitset_word tmp = *src1p++ & ~(*src2p++);
 
 
-         if (*dstp != tmp)
-           {
-             changed = 1;
-             *dstp = tmp;
-           }
+      if (*dstp != tmp)
+       {
+         changed = true;
+         *dstp = tmp;
        }
        }
-      break;
+    }
+  return changed;
+}
 
 
-    case BITSET_OP_AND:
-      for (i = 0; i < size; i++, dstp++)
-       {
-         bitset_word tmp = *src1p++ & *src2p++;
 
 
-         if (*dstp != tmp)
-           {
-             changed = 1;
-             *dstp = tmp;
-           }
-       }
-      break;
+static void
+abitset_or (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
 
 
-    case BITSET_OP_XOR:
-      for (i = 0; i < size; i++, dstp++)
-       {
-         bitset_word tmp = *src1p++ ^ *src2p++;
+  for (i = 0; i < size; i++)
+      *dstp++ = *src1p++ | *src2p++;
+}
 
 
-         if (*dstp != tmp)
-           {
-             changed = 1;
-             *dstp = tmp;
-           }
-       }
-      break;
 
 
-    case BITSET_OP_ANDN:
-      for (i = 0; i < size; i++, dstp++)
-       {
-         bitset_word tmp = *src1p++ & ~(*src2p++);
+static bool
+abitset_or_cmp (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
 
 
-         if (*dstp != tmp)
-           {
-             changed = 1;
-             *dstp = tmp;
-           }
-       }
-      break;
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = *src1p++ | *src2p++;
 
 
-    default:
-      abort ();
+      if (*dstp != tmp)
+       {
+         changed = true;
+         *dstp = tmp;
+       }
     }
     }
+  return changed;
+}
+
 
 
+static void
+abitset_xor (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = *src1p++ ^ *src2p++;
+}
+
+
+static bool
+abitset_xor_cmp (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = *src1p++ ^ *src2p++;
+
+      if (*dstp != tmp)
+       {
+         changed = true;
+         *dstp = tmp;
+       }
+    }
   return changed;
 }
 
 
   return changed;
 }
 
 
-static int
-abitset_op4 (dst, src1, src2, src3, op)
-     bitset dst;
-     bitset src1;
-     bitset src2;
-     bitset src3;
-     enum bitset_ops op;
+static void
+abitset_and_or (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = (*src1p++ & *src2p++) | *src3p++;
+}
+
+
+static bool
+abitset_and_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
 {
 {
-  unsigned int i;
-  int changed = 0;
+  bitset_windex i;
+  bool changed = false;
   bitset_word *src1p = ABITSET_WORDS (src1);
   bitset_word *src2p = ABITSET_WORDS (src2);
   bitset_word *src3p = ABITSET_WORDS (src3);
   bitset_word *dstp = ABITSET_WORDS (dst);
   bitset_windex size = dst->b.csize;
 
   bitset_word *src1p = ABITSET_WORDS (src1);
   bitset_word *src2p = ABITSET_WORDS (src2);
   bitset_word *src3p = ABITSET_WORDS (src3);
   bitset_word *dstp = ABITSET_WORDS (dst);
   bitset_windex size = dst->b.csize;
 
-  switch (op)
+  for (i = 0; i < size; i++, dstp++)
     {
     {
-    case BITSET_OP_OR_AND:
-      for (i = 0; i < size; i++, dstp++)
-       {
-         bitset_word tmp = (*src1p++ | *src2p++) & *src3p++;
+      bitset_word tmp = (*src1p++ & *src2p++) | *src3p++;
 
 
-         if (*dstp != tmp)
-           {
-             changed = 1;
-             *dstp = tmp;
-           }
+      if (*dstp != tmp)
+       {
+         changed = true;
+         *dstp = tmp;
        }
        }
-      break;
+    }
+  return changed;
+}
 
 
-    case BITSET_OP_AND_OR:
-      for (i = 0; i < size; i++, dstp++)
-       {
-         bitset_word tmp = (*src1p++ & *src2p++) | *src3p++;
 
 
-         if (*dstp != tmp)
-           {
-             changed = 1;
-             *dstp = tmp;
-           }
-       }
-      break;
+static void
+abitset_andn_or (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
 
 
-    case BITSET_OP_ANDN_OR:
-      for (i = 0; i < size; i++, dstp++)
-       {
-         bitset_word tmp = (*src1p++ & ~(*src2p++)) | *src3p++;
+  for (i = 0; i < size; i++)
+      *dstp++ = (*src1p++ & ~(*src2p++)) | *src3p++;
+}
 
 
-         if (*dstp != tmp)
-           {
-             changed = 1;
-             *dstp = tmp;
-           }
-       }
-      break;
 
 
-    default:
-      abort ();
+static bool
+abitset_andn_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = (*src1p++ & ~(*src2p++)) | *src3p++;
+
+      if (*dstp != tmp)
+       {
+         changed = true;
+         *dstp = tmp;
+       }
     }
     }
+  return changed;
+}
 
 
+
+static void
+abitset_or_and (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = (*src1p++ | *src2p++) & *src3p++;
+}
+
+
+static bool
+abitset_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = (*src1p++ | *src2p++) & *src3p++;
+
+      if (*dstp != tmp)
+       {
+         changed = true;
+         *dstp = tmp;
+       }
+    }
   return changed;
 }
 
 
   return changed;
 }
 
 
+static void
+abitset_copy (bitset dst, bitset src)
+{
+  if (BITSET_COMPATIBLE_ (dst, src))
+      abitset_copy1 (dst, src);
+  else
+      bitset_copy_ (dst, src);
+}
+
+
 /* Vector of operations for single word bitsets.  */
 /* Vector of operations for single word bitsets.  */
-struct bitset_ops_struct abitset_small_ops = {
+struct bitset_vtable abitset_small_vtable = {
   abitset_set,
   abitset_reset,
   abitset_set,
   abitset_reset,
+  bitset_toggle_,
   abitset_test,
   abitset_test,
-  abitset_size,
-  abitset_op1,
-  abitset_op2,
-  abitset_op3,
-  abitset_op4,
+  abitset_resize,
+  bitset_size_,
+  bitset_count_,
+  abitset_empty_p,
+  abitset_ones,
+  abitset_zero,
+  abitset_copy,
+  abitset_disjoint_p,
+  abitset_equal_p,
+  abitset_not,
+  abitset_subset_p,
+  abitset_and,
+  abitset_and_cmp,
+  abitset_andn,
+  abitset_andn_cmp,
+  abitset_or,
+  abitset_or_cmp,
+  abitset_xor,
+  abitset_xor_cmp,
+  abitset_and_or,
+  abitset_and_or_cmp,
+  abitset_andn_or,
+  abitset_andn_or_cmp,
+  abitset_or_and,
+  abitset_or_and_cmp,
   abitset_small_list,
   abitset_small_list,
-  abitset_reverse_list,
+  abitset_list_reverse,
   NULL,
   BITSET_ARRAY
 };
 
 
 /* Vector of operations for multiple word bitsets.  */
   NULL,
   BITSET_ARRAY
 };
 
 
 /* Vector of operations for multiple word bitsets.  */
-struct bitset_ops_struct abitset_ops = {
+struct bitset_vtable abitset_vtable = {
   abitset_set,
   abitset_reset,
   abitset_set,
   abitset_reset,
+  bitset_toggle_,
   abitset_test,
   abitset_test,
-  abitset_size,
-  abitset_op1,
-  abitset_op2,
-  abitset_op3,
-  abitset_op4,
+  abitset_resize,
+  bitset_size_,
+  bitset_count_,
+  abitset_empty_p,
+  abitset_ones,
+  abitset_zero,
+  abitset_copy,
+  abitset_disjoint_p,
+  abitset_equal_p,
+  abitset_not,
+  abitset_subset_p,
+  abitset_and,
+  abitset_and_cmp,
+  abitset_andn,
+  abitset_andn_cmp,
+  abitset_or,
+  abitset_or_cmp,
+  abitset_xor,
+  abitset_xor_cmp,
+  abitset_and_or,
+  abitset_and_or_cmp,
+  abitset_andn_or,
+  abitset_andn_or_cmp,
+  abitset_or_and,
+  abitset_or_and_cmp,
   abitset_list,
   abitset_list,
-  abitset_reverse_list,
+  abitset_list_reverse,
   NULL,
   BITSET_ARRAY
 };
 
 
   NULL,
   BITSET_ARRAY
 };
 
 
-int
-abitset_bytes (n_bits)
-     bitset_bindex n_bits;
+size_t
+abitset_bytes (bitset_bindex n_bits)
 {
 {
-  unsigned int bytes, size;
+  bitset_windex size;
+  size_t bytes;
+  size_t header_size = offsetof (union bitset_union, a.words);
+  struct bitset_align_struct { char a; union bitset_union b; };
+  size_t bitset_alignment = offsetof (struct bitset_align_struct, b);
 
   size = ABITSET_N_WORDS (n_bits);
 
   size = ABITSET_N_WORDS (n_bits);
-  bytes = size * sizeof (bitset_word);
-  return sizeof (struct bitset_struct) + bytes - sizeof (bitset_word);
+  bytes = header_size + size * sizeof (bitset_word);
+
+  /* Align the size properly for a vector of abitset objects.  */
+  if (header_size % bitset_alignment != 0
+      || sizeof (bitset_word) % bitset_alignment != 0)
+    {
+      bytes += bitset_alignment - 1;
+      bytes -= bytes % bitset_alignment;
+    }
+
+  return bytes;
 }
 
 
 bitset
 }
 
 
 bitset
-abitset_init (bset, n_bits)
-     bitset bset;
-     bitset_bindex n_bits;
+abitset_init (bitset bset, bitset_bindex n_bits)
 {
   bitset_windex size;
 
   size = ABITSET_N_WORDS (n_bits);
 {
   bitset_windex size;
 
   size = ABITSET_N_WORDS (n_bits);
-  ABITSET_N_BITS (bset) = n_bits;
+  BITSET_NBITS_ (bset) = n_bits;
 
   /* Use optimized routines if bitset fits within a single word.
      There is probably little merit if using caching since
      the small bitset will always fit in the cache.  */
   if (size == 1)
 
   /* Use optimized routines if bitset fits within a single word.
      There is probably little merit if using caching since
      the small bitset will always fit in the cache.  */
   if (size == 1)
-    bset->b.ops = &abitset_small_ops;
+    bset->b.vtable = &abitset_small_vtable;
   else
   else
-    bset->b.ops = &abitset_ops;
+    bset->b.vtable = &abitset_vtable;
 
   bset->b.cindex = 0;
   bset->b.csize = size;
 
   bset->b.cindex = 0;
   bset->b.csize = size;