X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fregex_internal.h;h=3616473446877403cab06096abf0150495a51894;hb=98ecea3646900dc98ece5e10364ef56647e49e2e;hp=74a52ecee25b26b49e218e5453a80e8b0d3525d0;hpb=151e40bb397d2664f467f529ac829ec4fd5a8353;p=gnulib.git diff --git a/lib/regex_internal.h b/lib/regex_internal.h index 74a52ecee..361647344 100644 --- a/lib/regex_internal.h +++ b/lib/regex_internal.h @@ -22,10 +22,15 @@ #include #include +#include #include #include #include +#ifndef _LIBC +# include "strcase.h" +#endif + #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC # include #endif @@ -83,15 +88,27 @@ # 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 @@ -114,7 +131,7 @@ # define attribute_hidden #endif /* not _LIBC */ -#ifdef __GNUC__ +#if __GNUC__ >= 3 # define __attribute(arg) __attribute__ (arg) #else # define __attribute(arg) @@ -123,26 +140,73 @@ 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,40 +382,40 @@ 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 the beginning of the input string. */ unsigned int tip_context; /* The translation passed as a part of an argument of re_compile_pattern. */ - unsigned RE_TRANSLATE_TYPE trans; + 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,45 +439,20 @@ typedef struct re_dfa_t re_dfa_t; # endif #endif -#ifndef RE_NO_INTERNAL_PROTOTYPES -static reg_errcode_t re_string_allocate (re_string_t *pstr, const char *str, - int len, int init_len, - RE_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, RE_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 +#ifdef RE_ENABLE_I18N static void build_wcs_buffer (re_string_t *pstr) internal_function; -static int build_wcs_upper_buffer (re_string_t *pstr) internal_function; -# endif /* RE_ENABLE_I18N */ +static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) + internal_function; +#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) +static unsigned int re_string_context_at (const re_string_t *input, + Idx idx, int eflags) 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) - internal_function __attribute ((pure)); -#endif + #define re_string_peek_byte(pstr, offset) \ ((pstr)->mbs[(pstr)->cur_idx + offset]) #define re_string_fetch_byte(pstr) \ @@ -431,10 +470,86 @@ static unsigned char re_string_fetch_byte_case (re_string_t *pstr) #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) +#include + +#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 + allocate anything larger than 4096 bytes. Also care for the possibility + of a few compiler-allocated temporary stack slots. */ +# define __libc_use_alloca(n) ((n) < 4032) +# else +/* alloca is implemented with malloc, so just use malloc. */ +# define __libc_use_alloca(n) 0 +# endif +#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; @@ -447,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; @@ -491,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; @@ -511,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; }; @@ -520,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; @@ -529,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; @@ -540,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; @@ -572,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; @@ -591,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; @@ -632,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 @@ -652,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 typedef enum @@ -721,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) { - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i) - dest[bitset_i] |= src[bitset_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) +{ + memset (set, 0, sizeof (bitset)); +} + +static inline void +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_not_merge (bitset dest, const bitset src) +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 < BITSET_UINTS; ++i) - dest[i] |= ~src[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_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) @@ -769,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]; @@ -778,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;