* regex_internal.h (__attribute): Define to nothing for GCC 2.
[gnulib.git] / lib / regex_internal.h
index edb5f8f..3616473 100644 (file)
 
 #include <assert.h>
 #include <ctype.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#ifndef _LIBC
+# include "strcase.h"
+#endif
+
 #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
 # include <langinfo.h>
 #endif
 # define RE_ENABLE_I18N
 #endif
 
+#ifndef __GNUC_PREREQ
+# if defined __GNUC__ && defined __GNUC_MINOR__
+#  define __GNUC_PREREQ(maj, min) \
+       ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+# else
+#  define __GNUC_PREREQ(maj, min) 0
+# endif
+#endif
+
+#if !__GNUC_PREREQ (3, 1)
+# define always_inline
+#endif
+
 #if __GNUC__ >= 3
 # define BE(expr, val) __builtin_expect (expr, val)
 #else
 # define BE(expr, val) (expr)
 # define inline
+# define pure
 #endif
 
-/* Number of bits in a byte.  */
-#define BYTE_BITS 8
 /* Number of single byte character.  */
 #define SBC_MAX 256
 
 # define attribute_hidden
 #endif /* not _LIBC */
 
-#ifdef __GNUC__
+#if __GNUC__ >= 3
 # define __attribute(arg) __attribute__ (arg)
 #else
 # define __attribute(arg)
 extern const char __re_error_msgid[] attribute_hidden;
 extern const size_t __re_error_msgid_idx[] attribute_hidden;
 
-/* Number of bits in an unsinged int.  */
-#define UINT_BITS (sizeof (unsigned int) * BYTE_BITS)
-/* Number of unsigned int in an bit_set.  */
-#define BITSET_UINTS ((SBC_MAX + UINT_BITS - 1) / UINT_BITS)
-typedef unsigned int bitset[BITSET_UINTS];
-typedef unsigned int *re_bitset_ptr_t;
-typedef const unsigned int *re_const_bitset_ptr_t;
-
-#define bitset_set(set,i) (set[i / UINT_BITS] |= 1 << i % UINT_BITS)
-#define bitset_clear(set,i) (set[i / UINT_BITS] &= ~(1 << i % UINT_BITS))
-#define bitset_contain(set,i) (set[i / UINT_BITS] & (1 << i % UINT_BITS))
-#define bitset_empty(set) memset (set, 0, sizeof (unsigned int) * BITSET_UINTS)
-#define bitset_set_all(set) \
-  memset (set, 255, sizeof (unsigned int) * BITSET_UINTS)
-#define bitset_copy(dest,src) \
-  memcpy (dest, src, sizeof (unsigned int) * BITSET_UINTS)
-static inline void bitset_not (bitset set);
-static inline void bitset_merge (bitset dest, const bitset src);
-static inline void bitset_not_merge (bitset dest, const bitset src);
-static inline void bitset_mask (bitset dest, const bitset src);
+typedef __re_idx_t Idx;
+
+/* Special return value for failure to match.  */
+#define REG_MISSING ((Idx) -1)
+
+/* Special return value for internal error.  */
+#define REG_ERROR ((Idx) -2)
+
+/* Test whether N is a valid index, and is not one of the above.  */
+#ifdef _REGEX_LARGE_OFFSETS
+# define REG_VALID_INDEX(n) ((Idx) (n) < REG_ERROR)
+#else
+# define REG_VALID_INDEX(n) (0 <= (n))
+#endif
+
+/* Test whether N is a valid nonzero index.  */
+#ifdef _REGEX_LARGE_OFFSETS
+# define REG_VALID_NONZERO_INDEX(n) ((Idx) ((n) - 1) < (Idx) (REG_ERROR - 1))
+#else
+# define REG_VALID_NONZERO_INDEX(n) (0 < (n))
+#endif
+
+/* A hash value, suitable for computing hash tables.  */
+typedef __re_size_t re_hashval_t;
+
+/* An integer used to represent a set of bits.  It must be unsigned,
+   and must be at least as wide as unsigned int.  */
+typedef unsigned long int bitset_word;
+
+/* Maximum value of a bitset word.  It must be useful in preprocessor
+   contexts, and must be consistent with bitset_word.  */
+#define BITSET_WORD_MAX ULONG_MAX
+
+/* Number of bits in a bitset word.  Avoid greater-than-32-bit
+   integers and unconditional shifts by more than 31 bits, as they're
+   not portable.  */
+#if BITSET_WORD_MAX == 0xffffffff
+# define BITSET_WORD_BITS 32
+#elif BITSET_WORD_MAX >> 31 >> 5 == 1
+# define BITSET_WORD_BITS 36
+#elif BITSET_WORD_MAX >> 31 >> 16 == 1
+# define BITSET_WORD_BITS 48
+#elif BITSET_WORD_MAX >> 31 >> 28 == 1
+# define BITSET_WORD_BITS 60
+#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1
+# define BITSET_WORD_BITS 64
+#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1
+# define BITSET_WORD_BITS 72
+#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1
+# define BITSET_WORD_BITS 128
+#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1
+# define BITSET_WORD_BITS 256
+#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1
+# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */
+# if BITSET_WORD_BITS <= SBC_MAX
+#  error "Invalid SBC_MAX"
+# endif
+#else
+# error "Add case for new bitset_word size"
+#endif
+
+/* Number of bitset words in a bitset.  */
+#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
+
+typedef bitset_word bitset[BITSET_WORDS];
+typedef bitset_word *re_bitset_ptr_t;
+typedef const bitset_word *re_const_bitset_ptr_t;
 
 #define PREV_WORD_CONSTRAINT 0x0001
 #define PREV_NOTWORD_CONSTRAINT 0x0002
@@ -171,9 +235,9 @@ typedef enum
 
 typedef struct
 {
-  int alloc;
-  int nelem;
-  int *elems;
+  Idx alloc;
+  Idx nelem;
+  Idx *elems;
 } re_node_set;
 
 typedef enum
@@ -259,19 +323,19 @@ typedef struct
   unsigned int non_match : 1;
 
   /* # of multibyte characters.  */
-  int nmbchars;
+  Idx nmbchars;
 
   /* # of collating symbols.  */
-  int ncoll_syms;
+  Idx ncoll_syms;
 
   /* # of equivalence classes. */
-  int nequiv_classes;
+  Idx nequiv_classes;
 
   /* # of range expressions. */
-  int nranges;
+  Idx nranges;
 
   /* # of character classes. */
-  int nchar_classes;
+  Idx nchar_classes;
 } re_charset_t;
 #endif /* RE_ENABLE_I18N */
 
@@ -284,7 +348,7 @@ typedef struct
 #ifdef RE_ENABLE_I18N
     re_charset_t *mbcset;      /* for COMPLEX_BRACKET */
 #endif /* RE_ENABLE_I18N */
-    int idx;                   /* for BACK_REF */
+    Idx idx;                   /* for BACK_REF */
     re_context_type ctx_type;  /* for ANCHOR */
   } opr;
 #if __GNUC__ >= 2
@@ -318,30 +382,30 @@ struct re_string_t
 #ifdef RE_ENABLE_I18N
   /* Store the wide character string which is corresponding to MBS.  */
   wint_t *wcs;
-  int *offsets;
+  Idx *offsets;
   mbstate_t cur_state;
 #endif
   /* Index in RAW_MBS.  Each character mbs[i] corresponds to
      raw_mbs[raw_mbs_idx + i].  */
-  int raw_mbs_idx;
+  Idx raw_mbs_idx;
   /* The length of the valid characters in the buffers.  */
-  int valid_len;
+  Idx valid_len;
   /* The corresponding number of bytes in raw_mbs array.  */
-  int valid_raw_len;
+  Idx valid_raw_len;
   /* The length of the buffers MBS and WCS.  */
-  int bufs_len;
+  Idx bufs_len;
   /* The index in MBS, which is updated by re_string_fetch_byte.  */
-  int cur_idx;
+  Idx cur_idx;
   /* length of RAW_MBS array.  */
-  int raw_len;
+  Idx raw_len;
   /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN.  */
-  int len;
+  Idx len;
   /* End of the buffer may be shorter than its length in the cases such
      as re_match_2, re_search_2.  Then, we use STOP for end of the buffer
      instead of LEN.  */
-  int raw_stop;
+  Idx raw_stop;
   /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS.  */
-  int stop;
+  Idx stop;
 
   /* The context of mbs[0].  We store the context independently, since
      the context of mbs[0] may be different from raw_mbs[0], which is
@@ -351,7 +415,7 @@ struct re_string_t
   unsigned REG_TRANSLATE_TYPE trans;
   /* Copy of re_dfa_t's word_char.  */
   re_const_bitset_ptr_t word_char;
-  /* 1 if REG_ICASE.  */
+  /* true if REG_ICASE.  */
   unsigned char icase;
   unsigned char is_utf8;
   unsigned char map_notascii;
@@ -375,19 +439,8 @@ typedef struct re_dfa_t re_dfa_t;
 # endif
 #endif
 
-static reg_errcode_t re_string_allocate (re_string_t *pstr, const char *str,
-                                        int len, int init_len,
-                                        REG_TRANSLATE_TYPE trans, int icase,
-                                        const re_dfa_t *dfa)
-     internal_function;
-static reg_errcode_t re_string_construct (re_string_t *pstr, const char *str,
-                                         int len, REG_TRANSLATE_TYPE trans,
-                                         int icase, const re_dfa_t *dfa)
-     internal_function;
-static reg_errcode_t re_string_reconstruct (re_string_t *pstr, int idx,
-                                           int eflags) internal_function;
 static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
-                                               int new_buf_len)
+                                               Idx new_buf_len)
      internal_function;
 #ifdef RE_ENABLE_I18N
 static void build_wcs_buffer (re_string_t *pstr) internal_function;
@@ -396,22 +449,8 @@ static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr)
 #endif /* RE_ENABLE_I18N */
 static void build_upper_buffer (re_string_t *pstr) internal_function;
 static void re_string_translate_buffer (re_string_t *pstr) internal_function;
-static void re_string_destruct (re_string_t *pstr) internal_function;
-#ifdef RE_ENABLE_I18N
-static int re_string_elem_size_at (const re_string_t *pstr, int idx)
-     internal_function __attribute ((pure));
-static inline int re_string_char_size_at (const re_string_t *pstr, int idx)
-     internal_function __attribute ((pure));
-static inline wint_t re_string_wchar_at (const re_string_t *pstr, int idx)
-     internal_function __attribute ((pure));
-#endif /* RE_ENABLE_I18N */
-static unsigned int re_string_context_at (const re_string_t *input, int idx,
-                                         int eflags)
-     internal_function __attribute ((pure));
-static unsigned char re_string_peek_byte_case (const re_string_t *pstr,
-                                              int idx)
-     internal_function __attribute ((pure));
-static unsigned char re_string_fetch_byte_case (re_string_t *pstr)
+static unsigned int re_string_context_at (const re_string_t *input,
+                                         Idx idx, int eflags)
      internal_function __attribute ((pure));
 
 #define re_string_peek_byte(pstr, offset) \
@@ -433,7 +472,7 @@ static unsigned char re_string_fetch_byte_case (re_string_t *pstr)
 
 #include <alloca.h>
 
-#ifndef __LIBC
+#ifndef _LIBC
 # if HAVE_ALLOCA
 /* The OS usually guarantees only one guard page at the bottom of the stack,
    and a page size can be as small as 4096 bytes.  So we cannot safely
@@ -447,10 +486,70 @@ static unsigned char re_string_fetch_byte_case (re_string_t *pstr)
 #endif
 
 #define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
+#define re_xmalloc(t,n) ((t *) re_xnmalloc (n, sizeof (t)))
 #define re_calloc(t,n) ((t *) calloc (n, sizeof (t)))
 #define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
+#define re_xrealloc(p,t,n) ((t *) re_xnrealloc (p, n, sizeof (t)))
+#define re_x2realloc(p,t,pn) ((t *) re_x2nrealloc (p, pn, sizeof (t)))
 #define re_free(p) free (p)
 
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+/* Return true if an array of N objects, each of size S, cannot exist
+   due to size arithmetic overflow.  S must be nonzero.  */
+static inline bool
+re_alloc_oversized (size_t n, size_t s)
+{
+  return BE (SIZE_MAX / s < n, 0);
+}
+
+/* Return true if an array of (2 * N + 1) objects, each of size S,
+   cannot exist due to size arithmetic overflow.  S must be nonzero.  */
+static inline bool
+re_x2alloc_oversized (size_t n, size_t s)
+{
+  return BE ((SIZE_MAX / s - 1) / 2 < n, 0);
+}
+
+/* Allocate an array of N objects, each with S bytes of memory,
+   dynamically, with error checking.  S must be nonzero.  */
+static inline void *
+re_xnmalloc (size_t n, size_t s)
+{
+  return re_alloc_oversized (n, s) ? NULL : malloc (n * s);
+}
+
+/* Change the size of an allocated block of memory P to an array of N
+   objects each of S bytes, with error checking.  S must be nonzero.  */
+static inline void *
+re_xnrealloc (void *p, size_t n, size_t s)
+{
+  return re_alloc_oversized (n, s) ? NULL : realloc (p, n * s);
+}
+
+/* Reallocate a block of memory P to an array of (2 * (*PN) + 1)
+   objects each of S bytes, with error checking.  S must be nonzero.
+   If the allocation is successful, set *PN to the new allocation
+   count and return the resulting pointer.  Otherwise, return
+   NULL.  */
+static inline void *
+re_x2nrealloc (void *p, size_t *pn, size_t s)
+{
+  if (re_x2alloc_oversized (*pn, s))
+    return NULL;
+  else
+    {
+      /* Add 1 in case *PN is zero.  */
+      size_t n1 = 2 * *pn + 1;
+      p = realloc (p, n1 * s);
+      if (BE (p != NULL, 1))
+       *pn = n1;
+      return p;
+    }
+}
+
 struct bin_tree_t
 {
   struct bin_tree_t *parent;
@@ -463,7 +562,7 @@ struct bin_tree_t
 
   /* `node_idx' is the index in dfa->nodes, if `type' == 0.
      Otherwise `type' indicate the type of this node.  */
-  int node_idx;
+  Idx node_idx;
 };
 typedef struct bin_tree_t bin_tree_t;
 
@@ -507,7 +606,7 @@ typedef struct bin_tree_storage_t bin_tree_storage_t;
 
 struct re_dfastate_t
 {
-  unsigned int hash;
+  re_hashval_t hash;
   re_node_set nodes;
   re_node_set non_eps_nodes;
   re_node_set inveclosure;
@@ -527,8 +626,8 @@ typedef struct re_dfastate_t re_dfastate_t;
 
 struct re_state_table_entry
 {
-  int num;
-  int alloc;
+  Idx num;
+  Idx alloc;
   re_dfastate_t **array;
 };
 
@@ -536,8 +635,8 @@ struct re_state_table_entry
 
 typedef struct
 {
-  int next_idx;
-  int alloc;
+  Idx next_idx;
+  Idx alloc;
   re_dfastate_t **array;
 } state_array_t;
 
@@ -545,8 +644,8 @@ typedef struct
 
 typedef struct
 {
-  int node;
-  int str_idx; /* The position NODE match at.  */
+  Idx node;
+  Idx str_idx; /* The position NODE match at.  */
   state_array_t path;
 } re_sub_match_last_t;
 
@@ -556,21 +655,20 @@ typedef struct
 
 typedef struct
 {
-  int str_idx;
-  int node;
-  int next_last_offset;
+  Idx str_idx;
+  Idx node;
   state_array_t *path;
-  int alasts; /* Allocation size of LASTS.  */
-  int nlasts; /* The number of LASTS.  */
+  Idx alasts; /* Allocation size of LASTS.  */
+  Idx nlasts; /* The number of LASTS.  */
   re_sub_match_last_t **lasts;
 } re_sub_match_top_t;
 
 struct re_backref_cache_entry
 {
-  int node;
-  int str_idx;
-  int subexp_from;
-  int subexp_to;
+  Idx node;
+  Idx str_idx;
+  Idx subexp_from;
+  Idx subexp_to;
   char more;
   char unused;
   unsigned short int eps_reachable_subexps_map;
@@ -588,18 +686,18 @@ typedef struct
   /* EFLAGS of the argument of regexec.  */
   int eflags;
   /* Where the matching ends.  */
-  int match_last;
-  int last_node;
+  Idx match_last;
+  Idx last_node;
   /* The state log used by the matcher.  */
   re_dfastate_t **state_log;
-  int state_log_top;
+  Idx state_log_top;
   /* Back reference cache.  */
-  int nbkref_ents;
-  int abkref_ents;
+  Idx nbkref_ents;
+  Idx abkref_ents;
   struct re_backref_cache_entry *bkref_ents;
   int max_mb_elem_len;
-  int nsub_tops;
-  int asub_tops;
+  Idx nsub_tops;
+  Idx asub_tops;
   re_sub_match_top_t **sub_tops;
 } re_match_context_t;
 
@@ -607,33 +705,33 @@ typedef struct
 {
   re_dfastate_t **sifted_states;
   re_dfastate_t **limited_states;
-  int last_node;
-  int last_str_idx;
+  Idx last_node;
+  Idx last_str_idx;
   re_node_set limits;
 } re_sift_context_t;
 
 struct re_fail_stack_ent_t
 {
-  int idx;
-  int node;
+  Idx idx;
+  Idx node;
   regmatch_t *regs;
   re_node_set eps_via_nodes;
 };
 
 struct re_fail_stack_t
 {
-  int num;
-  int alloc;
+  Idx num;
+  Idx alloc;
   struct re_fail_stack_ent_t *stack;
 };
 
 struct re_dfa_t
 {
   re_token_t *nodes;
-  int nodes_alloc;
-  int nodes_len;
-  int *nexts;
-  int *org_indices;
+  Idx nodes_alloc;
+  Idx nodes_len;
+  Idx *nexts;
+  Idx *org_indices;
   re_node_set *edests;
   re_node_set *eclosures;
   re_node_set *inveclosures;
@@ -648,14 +746,13 @@ struct re_dfa_t
   int str_tree_storage_idx;
 
   /* number of subexpressions `re_nsub' is in regex_t.  */
-  unsigned int state_hash_mask;
-  int states_alloc;
-  int init_node;
-  int nbackref; /* The number of backreference in this dfa.  */
+  re_hashval_t state_hash_mask;
+  Idx init_node;
+  Idx nbackref; /* The number of backreference in this dfa.  */
 
   /* Bitmap expressing which backreference is used.  */
-  unsigned int used_bkref_map;
-  unsigned int completed_bkref_map;
+  bitset_word used_bkref_map;
+  bitset_word completed_bkref_map;
 
   unsigned int has_plural_match : 1;
   /* If this dfa has "multibyte node", which is a backreference or
@@ -668,51 +765,20 @@ struct re_dfa_t
   int mb_cur_max;
   bitset word_char;
   reg_syntax_t syntax;
-  int *subexp_map;
+  Idx *subexp_map;
 #ifdef DEBUG
   char* re_str;
 #endif
   __libc_lock_define (, lock)
 };
 
-#ifndef RE_NO_INTERNAL_PROTOTYPES
-static reg_errcode_t re_node_set_alloc (re_node_set *set, int size) internal_function;
-static reg_errcode_t re_node_set_init_1 (re_node_set *set, int elem) internal_function;
-static reg_errcode_t re_node_set_init_2 (re_node_set *set, int elem1,
-                                        int elem2) internal_function;
 #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
-static reg_errcode_t re_node_set_init_copy (re_node_set *dest,
-                                           const re_node_set *src) internal_function;
-static reg_errcode_t re_node_set_add_intersect (re_node_set *dest,
-                                               const re_node_set *src1,
-                                               const re_node_set *src2) internal_function;
-static reg_errcode_t re_node_set_init_union (re_node_set *dest,
-                                            const re_node_set *src1,
-                                            const re_node_set *src2) internal_function;
-static reg_errcode_t re_node_set_merge (re_node_set *dest,
-                                       const re_node_set *src) internal_function;
-static int re_node_set_insert (re_node_set *set, int elem) internal_function;
-static int re_node_set_insert_last (re_node_set *set,
-                                   int elem) internal_function;
-static int re_node_set_compare (const re_node_set *set1,
-                               const re_node_set *set2)
-     internal_function __attribute ((pure));
-static int re_node_set_contains (const re_node_set *set, int elem)
-     internal_function __attribute ((pure));
-static void re_node_set_remove_at (re_node_set *set, int idx) internal_function;
 #define re_node_set_remove(set,id) \
   (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
 #define re_node_set_empty(p) ((p)->nelem = 0)
 #define re_node_set_free(set) re_free ((set)->elems)
-static int re_dfa_add_node (re_dfa_t *dfa, re_token_t token) internal_function;
-static re_dfastate_t *re_acquire_state (reg_errcode_t *err, re_dfa_t *dfa,
-                                       const re_node_set *nodes) internal_function;
-static re_dfastate_t *re_acquire_state_context (reg_errcode_t *err,
-                                               re_dfa_t *dfa,
-                                               const re_node_set *nodes,
-                                               unsigned int context) internal_function;
+
 static void free_state (re_dfastate_t *state) internal_function;
-#endif
 \f
 
 typedef enum
@@ -737,43 +803,79 @@ typedef struct
 
 
 /* Inline functions for bitset operation.  */
+
 static inline void
-bitset_not (bitset set)
+bitset_set (bitset set, Idx i)
 {
-  int bitset_i;
-  for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i)
-    set[bitset_i] = ~set[bitset_i];
+  set[i / BITSET_WORD_BITS] |= (bitset_word) 1 << i % BITSET_WORD_BITS;
 }
 
 static inline void
-bitset_merge (bitset dest, const bitset src)
+bitset_clear (bitset set, Idx i)
+{
+  set[i / BITSET_WORD_BITS] &= ~ ((bitset_word) 1 << i % BITSET_WORD_BITS);
+}
+
+static inline bool
+bitset_contain (const bitset set, Idx i)
+{
+  return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1;
+}
+
+static inline void
+bitset_empty (bitset set)
 {
-  int bitset_i;
-  for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i)
-    dest[bitset_i] |= src[bitset_i];
+  memset (set, 0, sizeof (bitset));
 }
 
 static inline void
-bitset_not_merge (bitset dest, const bitset src)
+bitset_set_all (bitset set)
+{
+  memset (set, -1, sizeof (bitset_word) * (SBC_MAX / BITSET_WORD_BITS));
+  if (SBC_MAX % BITSET_WORD_BITS != 0)
+    set[BITSET_WORDS - 1] =
+      ((bitset_word) 1 << SBC_MAX % BITSET_WORD_BITS) - 1;
+}
+
+static inline void
+bitset_copy (bitset dest, const bitset src)
+{
+  memcpy (dest, src, sizeof (bitset));
+}
+
+static inline void
+bitset_not (bitset set)
+{
+  int i;
+  for (i = 0; i < SBC_MAX / BITSET_WORD_BITS; ++i)
+    set[i] = ~set[i];
+  if (SBC_MAX % BITSET_WORD_BITS != 0)
+    set[BITSET_WORDS - 1] =
+      ((((bitset_word) 1 << SBC_MAX % BITSET_WORD_BITS) - 1)
+       & ~set[BITSET_WORDS - 1]);
+}
+
+static inline void
+bitset_merge (bitset dest, const bitset src)
 {
   int i;
-  for (i = 0; i < BITSET_UINTS; ++i)
-    dest[i] |= ~src[i];
+  for (i = 0; i < BITSET_WORDS; ++i)
+    dest[i] |= src[i];
 }
 
 static inline void
 bitset_mask (bitset dest, const bitset src)
 {
-  int bitset_i;
-  for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i)
-    dest[bitset_i] &= src[bitset_i];
+  int i;
+  for (i = 0; i < BITSET_WORDS; ++i)
+    dest[i] &= src[i];
 }
 
-#if defined RE_ENABLE_I18N && !defined RE_NO_INTERNAL_PROTOTYPES
+#if defined RE_ENABLE_I18N
 /* Inline functions for re_string.  */
 static inline int
-internal_function
-re_string_char_size_at (const re_string_t *pstr, int idx)
+internal_function __attribute ((pure))
+re_string_char_size_at (const re_string_t *pstr, Idx idx)
 {
   int byte_idx;
   if (pstr->mb_cur_max == 1)
@@ -785,8 +887,8 @@ re_string_char_size_at (const re_string_t *pstr, int idx)
 }
 
 static inline wint_t
-internal_function
-re_string_wchar_at (const re_string_t *pstr, int idx)
+internal_function __attribute ((pure))
+re_string_wchar_at (const re_string_t *pstr, Idx idx)
 {
   if (pstr->mb_cur_max == 1)
     return (wint_t) pstr->mbs[idx];
@@ -794,8 +896,8 @@ re_string_wchar_at (const re_string_t *pstr, int idx)
 }
 
 static int
-internal_function
-re_string_elem_size_at (const re_string_t *pstr, int idx)
+internal_function __attribute ((pure))
+re_string_elem_size_at (const re_string_t *pstr, Idx idx)
 {
 #ifdef _LIBC
   const unsigned char *p, *extra;