X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/7086e7071e8bfa2012e9134530a158c88a832ba6..3eb4f1a3e62807125a815dc572da9204b5b51865:/lib/lbitset.c?ds=sidebyside diff --git a/lib/lbitset.c b/lib/lbitset.c index e400df3d..ef7e216d 100644 --- a/lib/lbitset.c +++ b/lib/lbitset.c @@ -1,93 +1,95 @@ /* Functions to support link list bitsets. - Copyright (C) 2002 Free Software Foundation, Inc. + + Copyright (C) 2002-2004, 2006, 2009-2012 Free Software Foundation, Inc. + Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz). -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 -(at your option) any later version. + 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 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + 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 -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +#include + +#include "lbitset.h" -#include "bitset.h" #include "obstack.h" +#include #include - -# if WITH_DMALLOC -# define DMALLOC_FUNC_CHECK -# include -# endif /* WITH_DMALLOC */ +#include +#include /* This file implements linked-list bitsets. These bitsets can be of arbitrary length and are more efficient than arrays of bits for large sparse sets. - Usually if all the bits in an element are zero we remove the element - from the list. However, a side effect of the bit caching is that we - do not always notice when an element becomes zero. Hence the - lbitset_weed function which removes zero elements. */ + Usually if all the bits in an element are zero we remove the element + from the list. However, a side effect of the bit caching is that we + do not always notice when an element becomes zero. Hence the + lbitset_weed function which removes zero elements. */ + + +/* Number of words to use for each element. The larger the value the + greater the size of the cache and the shorter the time to find a given bit + but the more memory wasted for sparse bitsets and the longer the time + to search for set bits. + + The routines that dominate timing profiles are lbitset_elt_find + and lbitset_elt_link, especially when accessing the bits randomly. */ + +#define LBITSET_ELT_WORDS 2 + +typedef bitset_word lbitset_word; + +#define LBITSET_WORD_BITS BITSET_WORD_BITS + +/* Number of bits stored in each element. */ +#define LBITSET_ELT_BITS \ + ((unsigned int) (LBITSET_ELT_WORDS * LBITSET_WORD_BITS)) + +/* Lbitset element. We use an array of bits for each element. + These are linked together in a doubly-linked list. */ +typedef struct lbitset_elt_struct +{ + struct lbitset_elt_struct *next; /* Next element. */ + struct lbitset_elt_struct *prev; /* Previous element. */ + bitset_windex index; /* bitno / BITSET_WORD_BITS. */ + bitset_word words[LBITSET_ELT_WORDS]; /* Bits that are set. */ +} +lbitset_elt; -enum lbitset_find_mode {LBITSET_FIND, LBITSET_CREATE, LBITSET_SUBST}; + +enum lbitset_find_mode + { LBITSET_FIND, LBITSET_CREATE, LBITSET_SUBST }; static lbitset_elt lbitset_zero_elts[3]; /* Elements of all zero bits. */ /* Obstack to allocate bitset elements from. */ static struct obstack lbitset_obstack; -static int lbitset_obstack_init = 0; -static lbitset_elt *lbitset_free_list; /* Free list of bitset elements. */ - -static lbitset_elt *lbitset_elt_alloc PARAMS ((void)); -static lbitset_elt *lbitset_elt_calloc PARAMS ((void)); -static void lbitset_elt_link PARAMS ((bitset, lbitset_elt *)); -static void lbitset_elt_unlink PARAMS ((bitset, lbitset_elt *)); -static void lbitset_elt_free PARAMS ((lbitset_elt *)); -static lbitset_elt *lbitset_elt_find PARAMS ((bitset, bitset_windex, - enum lbitset_find_mode)); -static int lbitset_elt_zero_p PARAMS ((lbitset_elt *)); - -static void lbitset_prune PARAMS ((bitset, lbitset_elt *)); -static void lbitset_weed PARAMS ((bitset)); -static void lbitset_zero PARAMS((bitset)); -static int lbitset_equal_p PARAMS((bitset, bitset)); -static void lbitset_copy PARAMS((bitset, bitset)); -static int lbitset_copy_compare PARAMS((bitset, bitset)); -static void lbitset_set PARAMS((bitset, bitset_bindex)); -static void lbitset_reset PARAMS((bitset, bitset_bindex)); -static int lbitset_test PARAMS((bitset, bitset_bindex)); -static int lbitset_size PARAMS((bitset)); -static int lbitset_op1 PARAMS((bitset, enum bitset_ops)); -static int lbitset_op2 PARAMS((bitset, bitset, enum bitset_ops)); -static int lbitset_op3 PARAMS((bitset, bitset, bitset, enum bitset_ops)); -static int lbitset_op4 PARAMS((bitset, bitset, bitset, bitset, - enum bitset_ops)); -static int lbitset_list PARAMS((bitset, bitset_bindex *, bitset_bindex, - bitset_bindex *)); -static int lbitset_reverse_list PARAMS((bitset, bitset_bindex *, bitset_bindex, - bitset_bindex *)); -static void lbitset_free PARAMS((bitset)); - - -#define LBITSET_CURRENT1(X) (lbitset_elt *)((char *)(X) + ((char *)&(((lbitset_elt *)(X))->next) - (char *)&(((lbitset_elt *)(X))->words))) - -#define LBITSET_CURRENT(X) LBITSET_CURRENT1((X)->cdata) - -#define LBITSET_HEAD(X) ((X)->u.l.head) -#define LBITSET_TAIL(X) ((X)->u.l.tail) +static bool lbitset_obstack_init = false; +static lbitset_elt *lbitset_free_list; /* Free list of bitset elements. */ + +extern void debug_lbitset (bitset); + +#define LBITSET_CURRENT1(X) \ + ((lbitset_elt *) (void *) ((char *) (X) - offsetof (lbitset_elt, words))) + +#define LBITSET_CURRENT(X) LBITSET_CURRENT1((X)->b.cdata) + +#define LBITSET_HEAD(X) ((X)->l.head) +#define LBITSET_TAIL(X) ((X)->l.tail) /* Allocate a lbitset element. The bits are not cleared. */ static inline lbitset_elt * -lbitset_elt_alloc () +lbitset_elt_alloc (void) { lbitset_elt *elt; @@ -98,48 +100,49 @@ lbitset_elt_alloc () } else { - /* We can't use gcc_obstack_init to initialize the obstack since - print-rtl.c now calls bitset functions, and bitset is linked - into the gen* functions. */ if (!lbitset_obstack_init) - { - lbitset_obstack_init = 1; + { + lbitset_obstack_init = true; + + /* Let particular systems override the size of a chunk. */ - /* Let particular systems override the size of a chunk. */ #ifndef OBSTACK_CHUNK_SIZE #define OBSTACK_CHUNK_SIZE 0 #endif - /* Let them override the alloc and free routines too. */ + + /* Let them override the alloc and free routines too. */ + #ifndef OBSTACK_CHUNK_ALLOC #define OBSTACK_CHUNK_ALLOC xmalloc #endif + #ifndef OBSTACK_CHUNK_FREE #define OBSTACK_CHUNK_FREE free #endif -#if !defined(__GNUC__) || (__GNUC__ < 2) +#if ! defined __GNUC__ || __GNUC__ < 2 #define __alignof__(type) 0 #endif - obstack_specify_allocation (&lbitset_obstack, OBSTACK_CHUNK_SIZE, - __alignof__ (lbitset_elt), - (void *(*) PARAMS ((long))) OBSTACK_CHUNK_ALLOC, - (void (*) PARAMS ((void *))) OBSTACK_CHUNK_FREE); - } + obstack_specify_allocation (&lbitset_obstack, OBSTACK_CHUNK_SIZE, + __alignof__ (lbitset_elt), + OBSTACK_CHUNK_ALLOC, + OBSTACK_CHUNK_FREE); + } /* Perhaps we should add a number of new elements to the free list. */ elt = (lbitset_elt *) obstack_alloc (&lbitset_obstack, - sizeof (lbitset_elt)); + sizeof (lbitset_elt)); } return elt; } -/* Allocate a lbitset element. The bits are not cleared. */ +/* Allocate a lbitset element. The bits are cleared. */ static inline lbitset_elt * -lbitset_elt_calloc () +lbitset_elt_calloc (void) { lbitset_elt *elt; @@ -150,8 +153,7 @@ lbitset_elt_calloc () static inline void -lbitset_elt_free (elt) - lbitset_elt *elt; +lbitset_elt_free (lbitset_elt *elt) { elt->next = lbitset_free_list; lbitset_free_list = elt; @@ -160,9 +162,7 @@ lbitset_elt_free (elt) /* Unlink element ELT from bitset BSET. */ static inline void -lbitset_elt_unlink (bset, elt) - bitset bset; - lbitset_elt *elt; +lbitset_elt_unlink (bitset bset, lbitset_elt *elt) { lbitset_elt *next = elt->next; lbitset_elt *prev = elt->prev; @@ -184,20 +184,20 @@ lbitset_elt_unlink (bset, elt) if (LBITSET_CURRENT (bset) == elt) { if (next) - { - bset->cdata = next->words; - bset->cindex = next->index; - } + { + bset->b.cdata = next->words; + bset->b.cindex = next->index; + } else if (prev) - { - bset->cdata = prev->words; - bset->cindex = prev->index; - } + { + bset->b.cdata = prev->words; + bset->b.cindex = prev->index; + } else - { - bset->csize = 0; - bset->cdata = 0; - } + { + bset->b.csize = 0; + bset->b.cdata = 0; + } } lbitset_elt_free (elt); @@ -207,29 +207,27 @@ lbitset_elt_unlink (bset, elt) /* Cut the chain of bitset BSET before element ELT and free the elements. */ static inline void -lbitset_prune (bset, elt) - bitset bset; - lbitset_elt *elt; +lbitset_prune (bitset bset, lbitset_elt *elt) { lbitset_elt *next; if (!elt) - return; + return; if (elt->prev) - { + { LBITSET_TAIL (bset) = elt->prev; - bset->cdata = elt->prev->words; - bset->cindex = elt->prev->index; + bset->b.cdata = elt->prev->words; + bset->b.cindex = elt->prev->index; elt->prev->next = 0; - } + } else - { + { LBITSET_HEAD (bset) = 0; LBITSET_TAIL (bset) = 0; - bset->cdata = 0; - bset->csize = 0; - } + bset->b.cdata = 0; + bset->b.csize = 0; + } for (; elt; elt = next) { @@ -239,35 +237,32 @@ lbitset_prune (bset, elt) } -/* Return nonzero if all bits in an element are zero. */ -static inline int -lbitset_elt_zero_p (elt) - lbitset_elt *elt; +/* Are all bits in an element zero? */ +static inline bool +lbitset_elt_zero_p (lbitset_elt *elt) { int i; for (i = 0; i < LBITSET_ELT_WORDS; i++) if (elt->words[i]) - return 0; + return false; - return 1; + return true; } /* Link the bitset element into the current bitset linked list. */ static inline void -lbitset_elt_link (bset, elt) - bitset bset; - lbitset_elt *elt; +lbitset_elt_link (bitset bset, lbitset_elt *elt) { - bitset_windex index = elt->index; + bitset_windex windex = elt->index; lbitset_elt *ptr; lbitset_elt *current; - if (bset->csize) - current = LBITSET_CURRENT (bset); + if (bset->b.csize) + current = LBITSET_CURRENT (bset); else - current = LBITSET_HEAD (bset); + current = LBITSET_HEAD (bset); /* If this is the first and only element, add it in. */ if (LBITSET_HEAD (bset) == 0) @@ -279,17 +274,16 @@ lbitset_elt_link (bset, elt) /* If this index is less than that of the current element, it goes somewhere before the current element. */ - else if (index < bset->cindex) + else if (windex < bset->b.cindex) { for (ptr = current; - ptr->prev && ptr->prev->index > index; - ptr = ptr->prev) - continue; + ptr->prev && ptr->prev->index > windex; ptr = ptr->prev) + continue; if (ptr->prev) - ptr->prev->next = elt; + ptr->prev->next = elt; else - LBITSET_HEAD (bset) = elt; + LBITSET_HEAD (bset) = elt; elt->prev = ptr->prev; elt->next = ptr; @@ -300,14 +294,13 @@ lbitset_elt_link (bset, elt) else { for (ptr = current; - ptr->next && ptr->next->index < index; - ptr = ptr->next) - continue; + ptr->next && ptr->next->index < windex; ptr = ptr->next) + continue; if (ptr->next) - ptr->next->prev = elt; + ptr->next->prev = elt; else - LBITSET_TAIL (bset) = elt; + LBITSET_TAIL (bset) = elt; elt->next = ptr->next; elt->prev = ptr; @@ -315,27 +308,25 @@ lbitset_elt_link (bset, elt) } /* Set up so this is the first element searched. */ - bset->cindex = index; - bset->csize = LBITSET_ELT_WORDS; - bset->cdata = elt->words; + bset->b.cindex = windex; + bset->b.csize = LBITSET_ELT_WORDS; + bset->b.cdata = elt->words; } static lbitset_elt * -lbitset_elt_find (bset, index, mode) - bitset bset; - bitset_windex index; - enum lbitset_find_mode mode; +lbitset_elt_find (bitset bset, bitset_windex windex, + enum lbitset_find_mode mode) { lbitset_elt *elt; lbitset_elt *current; - if (bset->csize) + if (bset->b.csize) { current = LBITSET_CURRENT (bset); /* Check if element is the cached element. */ - if ((index - bset->cindex) < bset->csize) - return current; + if ((windex - bset->b.cindex) < bset->b.csize) + return current; } else { @@ -344,58 +335,56 @@ lbitset_elt_find (bset, index, mode) if (current) { - if (index < bset->cindex) - { - for (elt = current; - elt->prev && elt->index > index; - elt = elt->prev) - continue; - } + if (windex < bset->b.cindex) + { + for (elt = current; + elt->prev && elt->index > windex; elt = elt->prev) + continue; + } else - { - for (elt = current; - elt->next && (elt->index + LBITSET_ELT_WORDS - 1) < index; - elt = elt->next) - continue; - } - - /* `element' is the nearest to the one we want. If it's not the one - we want, the one we want does not exist. */ - if (elt && (index - elt->index) < LBITSET_ELT_WORDS) - { - bset->cindex = elt->index; - bset->csize = LBITSET_ELT_WORDS; - bset->cdata = elt->words; - return elt; - } + { + for (elt = current; + elt->next && (elt->index + LBITSET_ELT_WORDS - 1) < windex; + elt = elt->next) + continue; + } + + /* ELT is the nearest to the one we want. If it's not the one + we want, the one we want does not exist. */ + if (windex - elt->index < LBITSET_ELT_WORDS) + { + bset->b.cindex = elt->index; + bset->b.csize = LBITSET_ELT_WORDS; + bset->b.cdata = elt->words; + return elt; + } } switch (mode) { + default: + abort (); + case LBITSET_FIND: return 0; case LBITSET_CREATE: - index = (index / (unsigned) LBITSET_ELT_WORDS) * LBITSET_ELT_WORDS; + windex -= windex % LBITSET_ELT_WORDS; elt = lbitset_elt_calloc (); - elt->index = index; + elt->index = windex; lbitset_elt_link (bset, elt); return elt; case LBITSET_SUBST: return &lbitset_zero_elts[0]; - - default: - abort (); } } /* Weed out the zero elements from the list. */ static inline void -lbitset_weed (bset) - bitset bset; +lbitset_weed (bitset bset) { lbitset_elt *elt; lbitset_elt *next; @@ -404,15 +393,14 @@ lbitset_weed (bset) { next = elt->next; if (lbitset_elt_zero_p (elt)) - lbitset_elt_unlink (bset, elt); + lbitset_elt_unlink (bset, elt); } } /* Set all bits in the bitset to zero. */ -static inline void -lbitset_zero (bset) - bitset bset; +static void +lbitset_zero (bitset bset) { lbitset_elt *head; @@ -425,17 +413,16 @@ lbitset_zero (bset) } -static inline int -lbitset_equal_p (dst, src) - bitset dst; - bitset src; +/* Is DST == SRC? */ +static inline bool +lbitset_equal_p (bitset dst, bitset src) { lbitset_elt *selt; lbitset_elt *delt; int j; if (src == dst) - return 1; + return true; lbitset_weed (src); lbitset_weed (dst); @@ -443,21 +430,19 @@ lbitset_equal_p (dst, src) selt && delt; selt = selt->next, delt = delt->next) { if (selt->index != delt->index) - return 0; + return false; for (j = 0; j < LBITSET_ELT_WORDS; j++) - if (delt->words[j] != selt->words[j]) - return 0; + if (delt->words[j] != selt->words[j]) + return false; } - return ! selt && ! delt; + return !selt && !delt; } /* Copy bits from bitset SRC to bitset DST. */ static inline void -lbitset_copy (dst, src) - bitset dst; - bitset src; +lbitset_copy (bitset dst, bitset src) { lbitset_elt *elt; lbitset_elt *head; @@ -481,130 +466,113 @@ lbitset_copy (dst, src) tmp->prev = prev; tmp->next = 0; if (prev) - prev->next = tmp; + prev->next = tmp; else - LBITSET_HEAD (dst) = tmp; + LBITSET_HEAD (dst) = tmp; prev = tmp; memcpy (tmp->words, elt->words, sizeof (elt->words)); } LBITSET_TAIL (dst) = tmp; - dst->csize = LBITSET_ELT_WORDS; - dst->cdata = LBITSET_HEAD (dst)->words; - dst->cindex = LBITSET_HEAD (dst)->index; + dst->b.csize = LBITSET_ELT_WORDS; + dst->b.cdata = LBITSET_HEAD (dst)->words; + dst->b.cindex = LBITSET_HEAD (dst)->index; } -/* Copy bits from bitset SRC to bitset DST. Return non-zero if +/* Copy bits from bitset SRC to bitset DST. Return true if bitsets different. */ -static inline int -lbitset_copy_compare (dst, src) - bitset dst; - bitset src; +static inline bool +lbitset_copy_cmp (bitset dst, bitset src) { if (src == dst) - return 0; + return false; - if (! LBITSET_HEAD (dst)) + if (!LBITSET_HEAD (dst)) { lbitset_copy (dst, src); return LBITSET_HEAD (src) != 0; } if (lbitset_equal_p (dst, src)) - return 0; + return false; lbitset_copy (dst, src); - return 1; + return true; } -/* Return size in bits of bitset SRC. */ -static int -lbitset_size (src) - bitset src; +static bitset_bindex +lbitset_resize (bitset src, bitset_bindex size) { - lbitset_elt *elt; - - elt = LBITSET_TAIL (src); - if (!elt) - return 0; + BITSET_NBITS_ (src) = size; - /* Return current size of bitset in bits. */ - return (elt->index + LBITSET_ELT_WORDS) * BITSET_WORD_BITS; + /* Need to prune any excess bits. FIXME. */ + return size; } - /* Set bit BITNO in bitset DST. */ static void -lbitset_set (dst, bitno) - bitset dst; - bitset_bindex bitno; +lbitset_set (bitset dst, bitset_bindex bitno) { - bitset_windex index = bitno / BITSET_WORD_BITS; + bitset_windex windex = bitno / BITSET_WORD_BITS; - lbitset_elt_find (dst, index, LBITSET_CREATE); + lbitset_elt_find (dst, windex, LBITSET_CREATE); - dst->cdata[index - dst->cindex] |= (1 << (bitno % BITSET_WORD_BITS)); + dst->b.cdata[windex - dst->b.cindex] |= + (bitset_word) 1 << (bitno % BITSET_WORD_BITS); } /* Reset bit BITNO in bitset DST. */ static void -lbitset_reset (dst, bitno) - bitset dst; - bitset_bindex bitno; +lbitset_reset (bitset dst, bitset_bindex bitno) { - bitset_windex index = bitno / BITSET_WORD_BITS; + bitset_windex windex = bitno / BITSET_WORD_BITS; - if (!lbitset_elt_find (dst, index, LBITSET_FIND)) - return; + if (!lbitset_elt_find (dst, windex, LBITSET_FIND)) + return; - dst->cdata[index - dst->cindex] &= ~(1 << (bitno % BITSET_WORD_BITS)); + dst->b.cdata[windex - dst->b.cindex] &= + ~((bitset_word) 1 << (bitno % BITSET_WORD_BITS)); /* If all the data is zero, perhaps we should unlink it now... */ } /* Test bit BITNO in bitset SRC. */ -static int -lbitset_test (src, bitno) - bitset src; - bitset_bindex bitno; +static bool +lbitset_test (bitset src, bitset_bindex bitno) { - bitset_windex index = bitno / BITSET_WORD_BITS; - - if (!lbitset_elt_find (src, index, LBITSET_FIND)) - return 0; + bitset_windex windex = bitno / BITSET_WORD_BITS; - return (src->cdata[index - src->cindex] >> (bitno % BITSET_WORD_BITS)) & 1; + return (lbitset_elt_find (src, windex, LBITSET_FIND) + && ((src->b.cdata[windex - src->b.cindex] + >> (bitno % BITSET_WORD_BITS)) + & 1)); } static void -lbitset_free (bset) - bitset bset; +lbitset_free (bitset bset) { lbitset_zero (bset); } /* 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 -lbitset_reverse_list (bset, list, num, next) - bitset bset; - bitset_bindex *list; - bitset_bindex num; - bitset_bindex *next; + *NEXT and store in array LIST. Return with actual number of bits + found and with *NEXT indicating where search stopped. */ +static bitset_bindex +lbitset_list_reverse (bitset bset, bitset_bindex *list, + bitset_bindex num, bitset_bindex *next) { bitset_bindex rbitno; bitset_bindex bitno; - unsigned int bitcnt; - bitset_bindex bitoff; - bitset_windex index; + unsigned int bcount; + bitset_bindex boffset; + bitset_windex windex; bitset_bindex count; lbitset_elt *elt; bitset_word word; @@ -618,76 +586,85 @@ lbitset_reverse_list (bset, list, num, next) rbitno = *next; if (rbitno >= n_bits) - return 0; + return 0; bitno = n_bits - (rbitno + 1); - index = bitno / BITSET_WORD_BITS; + windex = bitno / BITSET_WORD_BITS; /* Skip back to starting element. */ - for (; elt && elt->index > index; elt = elt->prev) + for (; elt && elt->index > windex; elt = elt->prev) continue; if (!elt) return 0; - /* If num is 1, we could speed things up with a binary search - of the word of interest. */ + if (windex >= elt->index + LBITSET_ELT_WORDS) + { + /* We are trying to start in no-mans land so start + at end of current elt. */ + bcount = BITSET_WORD_BITS - 1; + windex = elt->index + LBITSET_ELT_WORDS - 1; + } + else + { + bcount = bitno % BITSET_WORD_BITS; + } count = 0; - bitcnt = bitno % BITSET_WORD_BITS; - bitoff = index * BITSET_WORD_BITS; + boffset = windex * BITSET_WORD_BITS; + + /* If num is 1, we could speed things up with a binary search + of the word of interest. */ while (elt) { bitset_word *srcp = elt->words; - for (; (index - elt->index) < LBITSET_ELT_WORDS; - index--, bitoff -= BITSET_WORD_BITS, - bitcnt = BITSET_WORD_BITS - 1) - { - word = srcp[index - elt->index] << (BITSET_WORD_BITS - 1 - bitcnt); - - for (; word; bitcnt--) - { - if (word & BITSET_MSB) - { - list[count++] = bitoff + bitcnt; - if (count >= num) - { - *next = n_bits - (bitoff + bitcnt); - return count; - } - } - word <<= 1; - } - } + for (; (windex - elt->index) < LBITSET_ELT_WORDS; + windex--, boffset -= BITSET_WORD_BITS, + bcount = BITSET_WORD_BITS - 1) + { + word = + srcp[windex - elt->index] << (BITSET_WORD_BITS - 1 - bcount); + + for (; word; bcount--) + { + if (word & BITSET_MSB) + { + list[count++] = boffset + bcount; + if (count >= num) + { + *next = n_bits - (boffset + bcount); + return count; + } + } + word <<= 1; + } + } elt = elt->prev; if (elt) - { - index = elt->index + LBITSET_ELT_WORDS - 1; - bitoff = index * BITSET_WORD_BITS; - } + { + windex = elt->index + LBITSET_ELT_WORDS - 1; + boffset = windex * BITSET_WORD_BITS; + } } - *next = n_bits - (bitoff + 1); + *next = n_bits - (boffset + 1); return count; } /* 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 -lbitset_list (bset, list, num, next) - bitset bset; - bitset_bindex *list; - bitset_bindex num; - bitset_bindex *next; + *NEXT and store in array LIST. Return with actual number of bits + found and with *NEXT indicating where search stopped. */ +static bitset_bindex +lbitset_list (bitset bset, bitset_bindex *list, + bitset_bindex num, bitset_bindex *next) { bitset_bindex bitno; - bitset_windex index; + bitset_windex windex; bitset_bindex count; lbitset_elt *elt; lbitset_elt *head; @@ -695,7 +672,7 @@ lbitset_list (bset, list, num, next) head = LBITSET_HEAD (bset); if (!head) - return 0; + return 0; bitno = *next; count = 0; @@ -706,60 +683,60 @@ lbitset_list (bset, list, num, next) /* Start with the first element. */ elt = head; - index = elt->index; - bitno = index * BITSET_WORD_BITS; + windex = elt->index; + bitno = windex * BITSET_WORD_BITS; } else { - index = bitno / BITSET_WORD_BITS; + windex = bitno / BITSET_WORD_BITS; /* Skip to starting element. */ for (elt = head; - elt && (elt->index + LBITSET_ELT_WORDS - 1) < index; - elt = elt->next) - continue; + elt && (elt->index + LBITSET_ELT_WORDS - 1) < windex; + elt = elt->next) + continue; if (!elt) - return 0; + return 0; - if (index < elt->index) - { - index = elt->index; - bitno = index * BITSET_WORD_BITS; - } + if (windex < elt->index) + { + windex = elt->index; + bitno = windex * BITSET_WORD_BITS; + } else - { - bitset_word *srcp = elt->words; - - /* We are starting within an element. */ - - for (; (index - elt->index) < LBITSET_ELT_WORDS; index++) - { - word = srcp[index - elt->index] >> (bitno % BITSET_WORD_BITS); - - for (; word; bitno++) - { - if (word & 1) - { - list[count++] = bitno; - if (count >= num) - { - *next = bitno + 1; - return count; - } - } - word >>= 1; - } - bitno = (index + 1) * BITSET_WORD_BITS; - } - - elt = elt->next; - if (elt) - { - index = elt->index; - bitno = index * BITSET_WORD_BITS; - } - } + { + bitset_word *srcp = elt->words; + + /* We are starting within an element. */ + + for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++) + { + word = srcp[windex - elt->index] >> (bitno % BITSET_WORD_BITS); + + for (; word; bitno++) + { + if (word & 1) + { + list[count++] = bitno; + if (count >= num) + { + *next = bitno + 1; + return count; + } + } + word >>= 1; + } + bitno = (windex + 1) * BITSET_WORD_BITS; + } + + elt = elt->next; + if (elt) + { + windex = elt->index; + bitno = windex * BITSET_WORD_BITS; + } + } } @@ -772,109 +749,109 @@ lbitset_list (bset, list, num, next) bitset_word *srcp = elt->words; if ((count + LBITSET_ELT_BITS) < num) - { - /* The coast is clear, plant boot! */ + { + /* The coast is clear, plant boot! */ #if LBITSET_ELT_WORDS == 2 - word = srcp[0]; - if (word) - { - if (! (word & 0xffff)) - { - word >>= 16; - bitno += 16; - } - if (! (word & 0xff)) - { - word >>= 8; - bitno += 8; - } - for (; word; bitno++) - { - if (word & 1) - list[count++] = bitno; - word >>= 1; - } - } - index++; - bitno = index * BITSET_WORD_BITS; - - word = srcp[1]; - if (word) - { - if (! (word & 0xffff)) - { - word >>= 16; - bitno += 16; - } - for (; word; bitno++) - { - if (word & 1) - list[count++] = bitno; - word >>= 1; - } - } - index++; - bitno = index * BITSET_WORD_BITS; + word = srcp[0]; + if (word) + { + if (!(word & 0xffff)) + { + word >>= 16; + bitno += 16; + } + if (!(word & 0xff)) + { + word >>= 8; + bitno += 8; + } + for (; word; bitno++) + { + if (word & 1) + list[count++] = bitno; + word >>= 1; + } + } + windex++; + bitno = windex * BITSET_WORD_BITS; + + word = srcp[1]; + if (word) + { + if (!(word & 0xffff)) + { + word >>= 16; + bitno += 16; + } + for (; word; bitno++) + { + if (word & 1) + list[count++] = bitno; + word >>= 1; + } + } + windex++; + bitno = windex * BITSET_WORD_BITS; #else - for (i = 0; i < LBITSET_ELT_WORDS; i++) - { - word = srcp[i]; - if (word) - { - if (! (word & 0xffff)) - { - word >>= 16; - bitno += 16; - } - if (! (word & 0xff)) - { - word >>= 8; - bitno += 8; - } - for (; word; bitno++) - { - if (word & 1) - list[count++] = bitno; - word >>= 1; - } - } - index++; - bitno = index * BITSET_WORD_BITS; - } + for (i = 0; i < LBITSET_ELT_WORDS; i++) + { + word = srcp[i]; + if (word) + { + if (!(word & 0xffff)) + { + word >>= 16; + bitno += 16; + } + if (!(word & 0xff)) + { + word >>= 8; + bitno += 8; + } + for (; word; bitno++) + { + if (word & 1) + list[count++] = bitno; + word >>= 1; + } + } + windex++; + bitno = windex * BITSET_WORD_BITS; + } #endif - } + } else - { - /* Tread more carefully since we need to check - if array overflows. */ - - for (i = 0; i < LBITSET_ELT_WORDS; i++) - { - for (word = srcp[i]; word; bitno++) - { - if (word & 1) - { - list[count++] = bitno; - if (count >= num) - { - *next = bitno + 1; - return count; - } - } - word >>= 1; - } - index++; - bitno = index * BITSET_WORD_BITS; - } - } + { + /* Tread more carefully since we need to check + if array overflows. */ + + for (i = 0; i < LBITSET_ELT_WORDS; i++) + { + for (word = srcp[i]; word; bitno++) + { + if (word & 1) + { + list[count++] = bitno; + if (count >= num) + { + *next = bitno + 1; + return count; + } + } + word >>= 1; + } + windex++; + bitno = windex * BITSET_WORD_BITS; + } + } elt = elt->next; if (elt) - { - index = elt->index; - bitno = index * BITSET_WORD_BITS; - } + { + windex = elt->index; + bitno = windex * BITSET_WORD_BITS; + } } *next = bitno; @@ -882,332 +859,330 @@ lbitset_list (bset, list, num, next) } -static int -lbitset_op1 (dst, op) - bitset dst; - enum bitset_ops op; +static bool +lbitset_empty_p (bitset dst) { - unsigned int i; - bitset_windex index; lbitset_elt *elt; + lbitset_elt *next; - switch (op) + for (elt = LBITSET_HEAD (dst); elt; elt = next) { - case BITSET_ZERO: - lbitset_zero (dst); - break; + next = elt->next; + if (!lbitset_elt_zero_p (elt)) + return 0; + /* Weed as we go. */ + lbitset_elt_unlink (dst, elt); + } + + return 1; +} + + +/* Ensure that any unused bits within the last element are clear. */ +static inline void +lbitset_unused_clear (bitset dst) +{ + unsigned int last_bit; + bitset_bindex n_bits; + + n_bits = BITSET_SIZE_ (dst); + last_bit = n_bits % LBITSET_ELT_BITS; + + if (last_bit) + { + lbitset_elt *elt; + bitset_windex windex; + bitset_word *srcp; - case BITSET_ONES: - /* This is a decidedly unfriendly operation for a linked list - bitset! */ elt = LBITSET_TAIL (dst); - /* Ignore empty set. */ - if (!elt) - return 0; - - index = elt->index; - for (i = 0; i < index; i += LBITSET_ELT_WORDS) - { - /* Create new elements if they cannot be found. */ - elt = lbitset_elt_find (dst, i, LBITSET_CREATE); - memset (elt->words, ~0, sizeof (elt->words)); - } - break; - - case BITSET_EMPTY_P: - lbitset_weed (dst); - if (LBITSET_HEAD (dst)) - return 0; - break; + srcp = elt->words; + windex = n_bits / BITSET_WORD_BITS; - default: - abort (); - } + srcp[windex - elt->index] &= ((bitset_word) 1 << last_bit) - 1; + windex++; - return 1; + for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++) + srcp[windex - elt->index] = 0; + } } -static int -lbitset_op2 (dst, src, op) - bitset dst; - bitset src; - enum bitset_ops op; +static void +lbitset_ones (bitset dst) { + bitset_windex i; + bitset_windex windex; lbitset_elt *elt; + + /* This is a decidedly unfriendly operation for a linked list + bitset! It makes a sparse bitset become dense. An alternative + is to have a flag that indicates that the bitset stores the + complement of what it indicates. */ + + windex = (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS; + + for (i = 0; i < windex; i += LBITSET_ELT_WORDS) + { + /* Create new elements if they cannot be found. */ + elt = lbitset_elt_find (dst, i, LBITSET_CREATE); + memset (elt->words, -1, sizeof (elt->words)); + } + + lbitset_unused_clear (dst); +} + + +static void +lbitset_not (bitset dst, bitset src) +{ lbitset_elt *selt; lbitset_elt *delt; - unsigned int i; + bitset_windex i; unsigned int j; - bitset_windex index; + bitset_windex windex; - switch (op) + windex = (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS; + + for (i = 0; i < windex; i += LBITSET_ELT_WORDS) { - case BITSET_COPY: - lbitset_copy (dst, src); - break; + /* Create new elements for dst if they cannot be found + or substitute zero elements if src elements not found. */ + selt = lbitset_elt_find (src, i, LBITSET_SUBST); + delt = lbitset_elt_find (dst, i, LBITSET_CREATE); - case BITSET_NOT: - /* This is another unfriendly operation for a linked list - bitset! */ - elt = LBITSET_TAIL (dst); - /* Ignore empty set. */ - if (!elt) - return 0; - - index = elt->index; - for (i = 0; i < index; i += LBITSET_ELT_WORDS) - { - /* Create new elements for dst if they cannot be found - or substitute zero elements if src elements not found. */ - selt = lbitset_elt_find (dst, i, LBITSET_SUBST); - delt = lbitset_elt_find (dst, i, LBITSET_CREATE); - - for (j = 0; j < LBITSET_ELT_WORDS; j++) - delt->words[j] = ~selt->words[j]; - } - lbitset_weed (dst); - break; - - case BITSET_EQUAL_P: - return lbitset_equal_p (dst, src); - break; - - case BITSET_SUBSET_P: - for (selt = LBITSET_HEAD (src), delt = LBITSET_HEAD (dst); - selt || delt; selt = selt->next, delt = delt->next) - { - if (!selt) - selt = &lbitset_zero_elts[0]; - else if (!delt) - delt = &lbitset_zero_elts[0]; - else if (selt->index != delt->index) - { - if (selt->index < delt->index) - { - lbitset_zero_elts[2].next = delt; - delt = &lbitset_zero_elts[2]; - } - else - { - lbitset_zero_elts[1].next = selt; - selt = &lbitset_zero_elts[1]; - } - } - - for (j = 0; j < LBITSET_ELT_WORDS; j++) - if (delt->words[j] != (selt->words[j] | delt->words[j])) - return 0; - } - break; + for (j = 0; j < LBITSET_ELT_WORDS; j++) + delt->words[j] = ~selt->words[j]; + } + lbitset_unused_clear (dst); + lbitset_weed (dst); + return; +} - default: - abort (); + +/* Is DST == DST | SRC? */ +static bool +lbitset_subset_p (bitset dst, bitset src) +{ + lbitset_elt *selt; + lbitset_elt *delt; + unsigned int j; + + for (selt = LBITSET_HEAD (src), delt = LBITSET_HEAD (dst); + selt || delt; selt = selt->next, delt = delt->next) + { + if (!selt) + selt = &lbitset_zero_elts[0]; + else if (!delt) + delt = &lbitset_zero_elts[0]; + else if (selt->index != delt->index) + { + if (selt->index < delt->index) + { + lbitset_zero_elts[2].next = delt; + delt = &lbitset_zero_elts[2]; + } + else + { + lbitset_zero_elts[1].next = selt; + selt = &lbitset_zero_elts[1]; + } + } + + for (j = 0; j < LBITSET_ELT_WORDS; j++) + if (delt->words[j] != (selt->words[j] | delt->words[j])) + return false; } + return true; +} - return 1; + +/* Is DST & SRC == 0? */ +static bool +lbitset_disjoint_p (bitset dst, bitset src) +{ + lbitset_elt *selt; + lbitset_elt *delt; + unsigned int j; + + for (selt = LBITSET_HEAD (src), delt = LBITSET_HEAD (dst); + selt && delt; selt = selt->next, delt = delt->next) + { + if (selt->index != delt->index) + { + if (selt->index < delt->index) + { + lbitset_zero_elts[2].next = delt; + delt = &lbitset_zero_elts[2]; + } + else + { + lbitset_zero_elts[1].next = selt; + selt = &lbitset_zero_elts[1]; + } + /* Since the elements are different, there is no + intersection of these elements. */ + continue; + } + + for (j = 0; j < LBITSET_ELT_WORDS; j++) + if (selt->words[j] & delt->words[j]) + return false; + } + return true; } -static int -lbitset_op3 (dst, src1, src2, op) - bitset dst; - bitset src1; - bitset src2; - enum bitset_ops op; +static bool +lbitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op) { lbitset_elt *selt1 = LBITSET_HEAD (src1); lbitset_elt *selt2 = LBITSET_HEAD (src2); lbitset_elt *delt = LBITSET_HEAD (dst); - bitset_windex index1; - bitset_windex index2; - bitset_windex index; + bitset_windex windex1; + bitset_windex windex2; + bitset_windex windex; lbitset_elt *stmp1; lbitset_elt *stmp2; lbitset_elt *dtmp; bitset_word *srcp1; bitset_word *srcp2; bitset_word *dstp; - int changed = 0; + bool changed = false; unsigned int i; - /* Fast track common, simple cases. */ - if (!selt2) - { - if (op == BITSET_AND) - { - lbitset_weed (dst); - changed = ! LBITSET_HEAD (dst); - lbitset_zero (dst); - return changed; - } - else if (op == BITSET_ANDN || op == BITSET_OR || op == BITSET_XOR) - { - return lbitset_copy_compare (dst, src1); - } - } - else if (!selt1) - { - if (op == BITSET_AND || op == BITSET_ANDN) - { - lbitset_weed (dst); - changed = ! LBITSET_HEAD (dst); - lbitset_zero (dst); - return changed; - } - else if (op == BITSET_OR || op == BITSET_XOR) - { - return lbitset_copy_compare (dst, src2); - } - } - - LBITSET_HEAD (dst) = 0; - dst->csize = 0; + dst->b.csize = 0; - index1 = (selt1) ? selt1->index : BITSET_INDEX_MAX; - index2 = (selt2) ? selt2->index : BITSET_INDEX_MAX; + windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX; + windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX; while (selt1 || selt2) { /* Figure out whether we need to substitute zero elements for - missing links. */ - if (index1 == index2) - { - index = index1; - stmp1 = selt1; - stmp2 = selt2; - selt1 = selt1->next; - index1 = (selt1) ? selt1->index : BITSET_INDEX_MAX; - selt2 = selt2->next; - index2 = (selt2) ? selt2->index : BITSET_INDEX_MAX; - } - else if (index1 < index2) - { - index = index1; - stmp1 = selt1; - stmp2 = &lbitset_zero_elts[0]; - selt1 = selt1->next; - index1 = (selt1) ? selt1->index : BITSET_INDEX_MAX; - } + missing links. */ + if (windex1 == windex2) + { + windex = windex1; + stmp1 = selt1; + stmp2 = selt2; + selt1 = selt1->next; + windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX; + selt2 = selt2->next; + windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX; + } + else if (windex1 < windex2) + { + windex = windex1; + stmp1 = selt1; + stmp2 = &lbitset_zero_elts[0]; + selt1 = selt1->next; + windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX; + } else - { - index = index2; - stmp1 = &lbitset_zero_elts[0]; - stmp2 = selt2; - selt2 = selt2->next; - index2 = (selt2) ? selt2->index : BITSET_INDEX_MAX; - } + { + windex = windex2; + stmp1 = &lbitset_zero_elts[0]; + stmp2 = selt2; + selt2 = selt2->next; + windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX; + } /* Find the appropriate element from DST. Begin by discarding - elements that we've skipped. */ - while (delt && delt->index < index) - { - changed = 1; - dtmp = delt; - delt = delt->next; - lbitset_elt_free (dtmp); - } - if (delt && delt->index == index) - { - dtmp = delt; - delt = delt->next; - } + elements that we've skipped. */ + while (delt && delt->index < windex) + { + changed = true; + dtmp = delt; + delt = delt->next; + lbitset_elt_free (dtmp); + } + if (delt && delt->index == windex) + { + dtmp = delt; + delt = delt->next; + } else - dtmp = lbitset_elt_calloc (); + dtmp = lbitset_elt_calloc (); /* Do the operation, and if any bits are set, link it into the - linked list. */ + linked list. */ srcp1 = stmp1->words; srcp2 = stmp2->words; dstp = dtmp->words; switch (op) - { - case BITSET_OR: - for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) - { - bitset_word tmp = *srcp1++ | *srcp2++; - - if (*dstp != tmp) - { - changed = 1; - *dstp = tmp; - } - } - break; - - case BITSET_AND: - for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) - { - bitset_word tmp = *srcp1++ & *srcp2++; - - if (*dstp != tmp) - { - changed = 1; - *dstp = tmp; - } - } - break; - - case BITSET_XOR: - for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) - { - bitset_word tmp = *srcp1++ ^ *srcp2++; - - if (*dstp != tmp) - { - changed = 1; - *dstp = tmp; - } - } - break; - - case BITSET_ANDN: - for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) - { - bitset_word tmp = *srcp1++ & ~(*srcp2++); - - if (*dstp != tmp) - { - changed = 1; - *dstp = tmp; - } - } - break; - - case BITSET_ORN: - for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) - { - bitset_word tmp = *srcp1++ | ~(*srcp2++); - - if (*dstp != tmp) - { - changed = 1; - *dstp = tmp; - } - } - break; - - default: - abort (); - } - - if (! lbitset_elt_zero_p (dtmp)) - { - dtmp->index = index; - /* Perhaps this could be optimised... */ - lbitset_elt_link (dst, dtmp); - } + { + default: + abort (); + + case BITSET_OP_OR: + for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) + { + bitset_word tmp = *srcp1++ | *srcp2++; + + if (*dstp != tmp) + { + changed = true; + *dstp = tmp; + } + } + break; + + case BITSET_OP_AND: + for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) + { + bitset_word tmp = *srcp1++ & *srcp2++; + + if (*dstp != tmp) + { + changed = true; + *dstp = tmp; + } + } + break; + + case BITSET_OP_XOR: + for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) + { + bitset_word tmp = *srcp1++ ^ *srcp2++; + + if (*dstp != tmp) + { + changed = true; + *dstp = tmp; + } + } + break; + + case BITSET_OP_ANDN: + for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) + { + bitset_word tmp = *srcp1++ & ~(*srcp2++); + + if (*dstp != tmp) + { + changed = true; + *dstp = tmp; + } + } + break; + } + + if (!lbitset_elt_zero_p (dtmp)) + { + dtmp->index = windex; + /* Perhaps this could be optimised... */ + lbitset_elt_link (dst, dtmp); + } else - { - lbitset_elt_free (dtmp); - } + { + lbitset_elt_free (dtmp); + } } /* If we have elements of DST left over, free them all. */ if (delt) { - changed = 1; + changed = true; lbitset_prune (dst, delt); } @@ -1215,107 +1190,211 @@ lbitset_op3 (dst, src1, src2, op) } -static int -lbitset_op4 (dst, src1, src2, src3, op) - bitset dst; - bitset src1; - bitset src2; - bitset src3; - enum bitset_ops op; +static bool +lbitset_and_cmp (bitset dst, bitset src1, bitset src2) { - int changed = 0; - bitset tmp; + lbitset_elt *selt1 = LBITSET_HEAD (src1); + lbitset_elt *selt2 = LBITSET_HEAD (src2); + bool changed; -#ifdef ENABLE_CHECKING - /* Check for compatiblity. */ - if (src1->ops != dst->ops || src2->ops != dst->ops || src3->ops != dst->ops) - abort (); -#endif + if (!selt2) + { + lbitset_weed (dst); + changed = !LBITSET_HEAD (dst); + lbitset_zero (dst); + return changed; + } + else if (!selt1) + { + lbitset_weed (dst); + changed = !LBITSET_HEAD (dst); + lbitset_zero (dst); + return changed; + } + return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_AND); +} - tmp = bitset_create (BITSET_LIST, 0); - switch (op) +static void +lbitset_and (bitset dst, bitset src1, bitset src2) +{ + lbitset_and_cmp (dst, src1, src2); +} + + +static bool +lbitset_andn_cmp (bitset dst, bitset src1, bitset src2) +{ + lbitset_elt *selt1 = LBITSET_HEAD (src1); + lbitset_elt *selt2 = LBITSET_HEAD (src2); + bool changed; + + if (!selt2) { - case BITSET_OR_AND: - bitset_or (tmp, src1, src2); - changed = bitset_and (dst, src3, tmp); - break; + return lbitset_copy_cmp (dst, src1); + } + else if (!selt1) + { + lbitset_weed (dst); + changed = !LBITSET_HEAD (dst); + lbitset_zero (dst); + return changed; + } + return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_ANDN); +} - case BITSET_AND_OR: - bitset_and (tmp, src1, src2); - changed = bitset_or (dst, src3, tmp); - break; - case BITSET_ANDN_OR: - bitset_andn (tmp, src1, src2); - changed = bitset_or (dst, src3, tmp); - break; +static void +lbitset_andn (bitset dst, bitset src1, bitset src2) +{ + lbitset_andn_cmp (dst, src1, src2); +} - default: - abort (); + +static bool +lbitset_or_cmp (bitset dst, bitset src1, bitset src2) +{ + lbitset_elt *selt1 = LBITSET_HEAD (src1); + lbitset_elt *selt2 = LBITSET_HEAD (src2); + + if (!selt2) + { + return lbitset_copy_cmp (dst, src1); } + else if (!selt1) + { + return lbitset_copy_cmp (dst, src2); + } + return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_OR); +} - bitset_free (tmp); - return changed; + +static void +lbitset_or (bitset dst, bitset src1, bitset src2) +{ + lbitset_or_cmp (dst, src1, src2); } +static bool +lbitset_xor_cmp (bitset dst, bitset src1, bitset src2) +{ + lbitset_elt *selt1 = LBITSET_HEAD (src1); + lbitset_elt *selt2 = LBITSET_HEAD (src2); + + if (!selt2) + { + return lbitset_copy_cmp (dst, src1); + } + else if (!selt1) + { + return lbitset_copy_cmp (dst, src2); + } + return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_XOR); +} + + +static void +lbitset_xor (bitset dst, bitset src1, bitset src2) +{ + lbitset_xor_cmp (dst, src1, src2); +} + + + /* Vector of operations for linked-list bitsets. */ -struct bitset_ops_struct lbitset_ops = - { - lbitset_set, - lbitset_reset, - lbitset_test, - lbitset_size, - lbitset_op1, - lbitset_op2, - lbitset_op3, - lbitset_op4, - lbitset_list, - lbitset_reverse_list, - lbitset_free, - BITSET_LIST - }; +struct bitset_vtable lbitset_vtable = { + lbitset_set, + lbitset_reset, + bitset_toggle_, + lbitset_test, + lbitset_resize, + bitset_size_, + bitset_count_, + lbitset_empty_p, + lbitset_ones, + lbitset_zero, + lbitset_copy, + lbitset_disjoint_p, + lbitset_equal_p, + lbitset_not, + lbitset_subset_p, + lbitset_and, + lbitset_and_cmp, + lbitset_andn, + lbitset_andn_cmp, + lbitset_or, + lbitset_or_cmp, + lbitset_xor, + lbitset_xor_cmp, + bitset_and_or_, + bitset_and_or_cmp_, + bitset_andn_or_, + bitset_andn_or_cmp_, + bitset_or_and_, + bitset_or_and_cmp_, + lbitset_list, + lbitset_list_reverse, + lbitset_free, + BITSET_LIST +}; /* Return size of initial structure. */ -int -lbitset_bytes (n_bits) - bitset_bindex n_bits ATTRIBUTE_UNUSED; +size_t +lbitset_bytes (bitset_bindex n_bits ATTRIBUTE_UNUSED) { - return sizeof (struct bitset_struct); + return sizeof (struct lbitset_struct); } /* Initialize a bitset. */ - bitset -lbitset_init (bset, n_bits) - bitset bset; - bitset_bindex n_bits ATTRIBUTE_UNUSED; +lbitset_init (bitset bset, bitset_bindex n_bits ATTRIBUTE_UNUSED) { - LBITSET_HEAD (bset) = 0; - LBITSET_TAIL (bset) = 0; - - bset->ops = &lbitset_ops; - - bset->cindex = 0; - /* Disable cache until have some elements allocated. - If we have variable length arrays, then we may - need to allocate dummy element. */ - bset->csize = 0; - bset->cdata = 0; + BITSET_NBITS_ (bset) = n_bits; + bset->b.vtable = &lbitset_vtable; return bset; } void -lbitset_release_memory () +lbitset_release_memory (void) { lbitset_free_list = 0; if (lbitset_obstack_init) { - lbitset_obstack_init = 0; + lbitset_obstack_init = false; obstack_free (&lbitset_obstack, NULL); } } + + +/* Function to be called from debugger to debug lbitset. */ +void +debug_lbitset (bitset bset) +{ + lbitset_elt *elt; + unsigned int i; + + if (!bset) + return; + + for (elt = LBITSET_HEAD (bset); elt; elt = elt->next) + { + fprintf (stderr, "Elt %lu\n", (unsigned long int) elt->index); + for (i = 0; i < LBITSET_ELT_WORDS; i++) + { + unsigned int j; + bitset_word word; + + word = elt->words[i]; + + fprintf (stderr, " Word %u:", i); + for (j = 0; j < LBITSET_WORD_BITS; j++) + if ((word & ((bitset_word) 1 << j))) + fprintf (stderr, " %u", j); + fprintf (stderr, "\n"); + } + } +}