Index: user/gabor/tre-integration/contrib/tre/lib/hashtable.c =================================================================== --- user/gabor/tre-integration/contrib/tre/lib/hashtable.c (revision 225155) +++ user/gabor/tre-integration/contrib/tre/lib/hashtable.c (revision 225156) @@ -1,157 +1,218 @@ /*- * Copyright (C) 2011 Gabor Kovesdan * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include -#include + +#include #include #include +#include "hashtable.h" + +/* + * Initializes a hash table that can hold table_size number of entries, + * each of which has a key of key_size bytes and a value of value_size + * bytes. On successful allocation returns a pointer to the hash table. + * Otherwise, returns NULL and sets errno to indicate the error. + */ hashtable *hashtable_init(size_t table_size, size_t key_size, size_t value_size) { hashtable *tbl; tbl = malloc(sizeof(hashtable)); if (tbl == NULL) - return (NULL); + goto mem1; tbl->entries = calloc(sizeof(hashtable_entry *), table_size); - if (tbl->entries == NULL) { - free(tbl); - return (NULL); - } + if (tbl->entries == NULL) + goto mem2; tbl->table_size = table_size; tbl->usage = 0; tbl->key_size = key_size; tbl->value_size = value_size; return (tbl); + +mem2: + free(tbl); +mem1: + errno = ENOMEM; + return (NULL); } +/* + * Places the key-value pair to the hashtable tbl. + * Returns: + * HASH_OK: if the key was not present in the hash table yet + * but the kay-value pair has been successfully added. + * HASH_UPDATED: if the value for the key has been updated with the + * new value. + * HASH_FULL: if the hash table is full and the entry could not + * be added. + * HASH_FAIL: if an error has occurred and errno has been set to + * indicate the error. + */ int hashtable_put(hashtable *tbl, const void *key, const void *value) { uint32_t hash = 0; - if (tbl->table_size == tbl->usage) - return (-1); + if (tbl->table_size == tbl->usage) { + return (HASH_FULL); + } - hash = hash32_buf(key, tbl->key_size, hash); - hash %= tbl->table_size; + hash = hash32_buf(key, tbl->key_size, hash) % tbl->table_size; + /* + * On hash collision entries are inserted at the next free space, + * so we have to increase the index until we either find an entry + * with the same key (and update it) or we find a free space. + */ + for(;;) { + if (tbl->entries[hash] == NULL) + break; + else if (memcmp(tbl->entries[hash]->key, key, + tbl->key_size) == 0) { + memcpy(tbl->entries[hash]->value, value, tbl->value_size); + return (HASH_UPDATED); + } + } + while (tbl->entries[hash] != NULL) hash = (hash >= tbl->table_size) ? 0 : hash + 1; tbl->entries[hash] = malloc(sizeof(hashtable_entry)); - if (tbl->entries[hash] == NULL) - return (-1); + if (tbl->entries[hash] == NULL) { + errno = ENOMEM; + goto mem1; + } tbl->entries[hash]->key = malloc(tbl->key_size); if (tbl->entries[hash]->key == NULL) { - free(tbl->entries[hash]); - return (-1); + errno = ENOMEM; + goto mem2; } tbl->entries[hash]->value = malloc(tbl->value_size); if (tbl->entries[hash]->value == NULL) { - free(tbl->entries[hash]->key); - free(tbl->entries[hash]); - return (-1); + errno = ENOMEM; + goto mem3; } - memcpy(&tbl->entries[hash]->key, key, tbl->key_size); - memcpy(&tbl->entries[hash]->value, value, tbl->value_size); + memcpy(tbl->entries[hash]->key, key, tbl->key_size); + memcpy(tbl->entries[hash]->value, value, tbl->value_size); tbl->usage++; - return (0); + return (HASH_OK); + +mem3: + free(tbl->entries[hash]->key); +mem2: + free(tbl->entries[hash]); +mem1: + return (HASH_FAIL); } static hashtable_entry -*hashtable_lookup(const hashtable *tbl, const void *key) +**hashtable_lookup(const hashtable *tbl, const void *key) { uint32_t hash = 0; - hash = hash32_buf(key, tbl->key_size, hash); - hash %= tbl->table_size; + hash = hash32_buf(key, tbl->key_size, hash) % tbl->table_size; for (;;) { if (tbl->entries[hash] == NULL) return (NULL); - else if (memcmp(key, &tbl->entries[hash]->key, + else if (memcmp(key, tbl->entries[hash]->key, tbl->key_size) == 0) - return (tbl->entries[hash]); + return (&tbl->entries[hash]); hash = (hash == tbl->table_size) ? 0 : hash + 1; } } +/* + * Retrieves the value for key from the hash table tbl and places + * it to the space indicated by the value argument. + * Returns HASH_OK if the value has been found and retrieved or + * HASH_NOTFOUND otherwise. + */ int hashtable_get(hashtable *tbl, const void *key, void *value) { - hashtable_entry *entry; + hashtable_entry **entry; entry = hashtable_lookup(tbl, key); if (entry == NULL) - return (-1); + return (HASH_NOTFOUND); - memcpy(value, &entry->value, tbl->value_size); - return (0); + memcpy(value, (*entry)->value, tbl->value_size); + return (HASH_OK); } +/* + * Removes the entry with the specifified key from the hash table + * tbl. Returns HASH_OK if the entry has been found and removed + * or HASH_NOTFOUND otherwise. + */ int hashtable_remove(hashtable *tbl, const void *key) { - hashtable_entry *entry; + hashtable_entry **entry; entry = hashtable_lookup(tbl, key); if (entry == NULL) - return (-1); + return (HASH_NOTFOUND); -// free(entry->key); -// free(entry->value); - free(entry); + free((*entry)->key); + free((*entry)->value); + free(*entry); + *entry = NULL; tbl->usage--; - return (0); + return (HASH_OK); } +/* + * Frees the resources associated with the hash table tbl. + */ void hashtable_free(hashtable *tbl) { if (tbl == NULL) return; for (unsigned int i = 0; i < tbl->table_size; i++) - if (tbl->entries[i] != NULL) { -// free(tbl->entries[i]->key); -// free(tbl->entries[i]->value); -// free(tbl->entries[i]); - } + if ((tbl->entries[i] != NULL)) { + free(tbl->entries[i]->key); + free(tbl->entries[i]->value); + } free(tbl->entries); } Index: user/gabor/tre-integration/contrib/tre/lib/hashtable.h =================================================================== --- user/gabor/tre-integration/contrib/tre/lib/hashtable.h (nonexistent) +++ user/gabor/tre-integration/contrib/tre/lib/hashtable.h (revision 225156) @@ -0,0 +1,33 @@ +/* $FreeBSD$ */ + +#ifndef HASHTABLE_H +#define HASHTABLE_H 1 + +#include + +#define HASH_OK 0 +#define HASH_UPDATED 1 +#define HASH_FAIL 2 +#define HASH_FULL 3 +#define HASH_NOTFOUND 4 + +typedef struct { + void *key; + void *value; +} hashtable_entry; + +typedef struct { + size_t key_size; + size_t table_size; + size_t usage; + size_t value_size; + hashtable_entry **entries; +} hashtable; + +void hashtable_free(hashtable *); +int hashtable_get(hashtable *, const void *, void *); +hashtable *hashtable_init(size_t, size_t, size_t); +int hashtable_put(hashtable *, const void *, const void *); +int hashtable_remove(hashtable *, const void *); + +#endif /* HASHTABLE.H */ Property changes on: user/gabor/tre-integration/contrib/tre/lib/hashtable.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/gabor/tre-integration/contrib/tre/lib/tre-fastmatch.c =================================================================== --- user/gabor/tre-integration/contrib/tre/lib/tre-fastmatch.c (revision 225155) +++ user/gabor/tre-integration/contrib/tre/lib/tre-fastmatch.c (revision 225156) @@ -1,720 +1,719 @@ /*- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav * Copyright (C) 2008-2011 Gabor Kovesdan * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ -#include #include #include #include #include #include #ifdef TRE_WCHAR #include #include #endif #include "hashtable.h" #include "tre-fastmatch.h" #include "tre-internal.h" #include "xmalloc.h" static int fastcmp(const void *, const void *, size_t, tre_str_type_t, bool, bool); /* * Skips n characters in the input string and assigns the start * address to startptr. Note: as per IEEE Std 1003.1-2008 * matching is based on bit pattern not character representations * so we can handle MB strings as byte sequences just like * SB strings. */ #define SKIP_CHARS(n) \ switch (type) \ { \ case STR_WIDE: \ startptr = str_wide + n; \ break; \ default: \ startptr = str_byte + n; \ } /* * Converts the wide string pattern to SB/MB string and stores * it in fg->pattern. Sets fg->len to the byte length of the * converted string. */ #define STORE_MBS_PAT \ { \ size_t siz; \ \ siz = wcstombs(NULL, fg->wpattern, 0); \ if (siz == (size_t)-1) \ return REG_BADPAT; \ fg->len = siz; \ fg->pattern = xmalloc(siz + 1); \ if (fg->pattern == NULL) \ return REG_ESPACE; \ wcstombs(fg->pattern, fg->wpattern, siz); \ fg->pattern[siz] = '\0'; \ } \ /* * Compares the pattern to the input string at the position * stored in startptr. */ #define COMPARE \ switch (type) \ { \ case STR_WIDE: \ mismatch = fastcmp(fg->wpattern, startptr, fg->wlen, type, \ fg->icase, fg->newline); \ break; \ default: \ mismatch = fastcmp(fg->pattern, startptr, fg->len, type, \ fg->icase, fg->newline); \ } \ #define IS_OUT_OF_BOUNDS \ ((type == STR_WIDE) ? ((j + fg->wlen) > len) : ((j + fg->len) > len)) /* * Checks whether the new position after shifting in the input string * is out of the bounds and break out from the loop if so. */ #define CHECKBOUNDS \ if (IS_OUT_OF_BOUNDS) \ break; \ /* * Shifts in the input string after a mismatch. The position of the * mismatch is stored in the mismatch variable. */ #define SHIFT \ CHECKBOUNDS; \ \ { \ int bc = 0, gs = 0, ts, r = -1; \ \ switch (type) \ { \ case STR_WIDE: \ if (!fg->hasdot) \ { \ if (u != 0 && mismatch == fg->wlen - 1 - shift) \ mismatch -= u; \ v = fg->wlen - 1 - mismatch; \ r = hashtable_get(fg->qsBc_table, \ &((tre_char_t *)startptr)[mismatch + 1], &bc); \ gs = fg->bmGs[mismatch]; \ } \ - bc = (r == 0) ? bc : fg->defBc; \ + bc = (r == HASH_OK) ? bc : fg->defBc; \ DPRINT(("tre_fast_match: mismatch on character %lc," \ "BC %d, GS %d\n", \ ((tre_char_t *)startptr)[mismatch + 1], bc, gs)); \ break; \ default: \ if (!fg->hasdot) \ { \ if (u != 0 && mismatch == fg->len - 1 - shift) \ mismatch -= u; \ v = fg->len - 1 - mismatch; \ gs = fg->sbmGs[mismatch]; \ } \ bc = fg->qsBc[((unsigned char *)startptr)[mismatch + 1]]; \ DPRINT(("tre_fast_match: mismatch on character %c," \ "BC %d, GS %d\n", \ ((unsigned char *)startptr)[mismatch + 1], bc, gs)); \ } \ if (fg->hasdot) \ shift = bc; \ else \ { \ ts = u - v; \ shift = MAX(ts, bc); \ shift = MAX(shift, gs); \ if (shift == gs) \ u = MIN((type == STR_WIDE ? fg->wlen : fg->len) - shift, v); \ else \ { \ if (ts < bc) \ shift = MAX(shift, u + 1); \ u = 0; \ } \ } \ DPRINT(("tre_fast_match: shifting %d characters\n", shift)); \ j += shift; \ } /* * Normal Quick Search would require a shift based on the position the * next character after the comparison is within the pattern. With * wildcards, the position of the last dot effects the maximum shift * distance. * The closer to the end the wild card is the slower the search. * * Examples: * Pattern Max shift * ------- --------- * this 5 * .his 4 * t.is 3 * th.s 2 * thi. 1 */ /* * Fills in the bad character shift array for SB/MB strings. */ #define FILL_QSBC \ for (unsigned int i = 0; i <= UCHAR_MAX; i++) \ fg->qsBc[i] = fg->len - fg->hasdot; \ for (int i = fg->hasdot + 1; i < fg->len; i++) \ { \ fg->qsBc[(unsigned)fg->pattern[i]] = fg->len - i; \ DPRINT(("BC shift for char %c is %d\n", fg->pattern[i], \ fg->len - i)); \ if (fg->icase) \ { \ char c = islower(fg->pattern[i]) ? toupper(fg->pattern[i]) \ : tolower(fg->pattern[i]); \ fg->qsBc[(unsigned)c] = fg->len - i; \ } \ } /* * Fills in the bad character shifts into a hastable for wide strings. * With wide characters it is not possible any more to use a normal * array because there are too many characters and we could not * provide enough memory. Fortunately, we only have to store distinct * values for so many characters as the number of distinct characters * in the pattern, so we can store them in a hashtable and store a * default shift value for the rest. */ #define FILL_QSBC_WIDE \ /* Adjust the shift based on location of the last dot ('.'). */ \ fg->defBc = fg->wlen - fg->hasdot; \ \ /* Preprocess pattern. */ \ fg->qsBc_table = hashtable_init(fg->wlen * 4, sizeof(tre_char_t), \ sizeof(int)); \ for (unsigned int i = fg->hasdot + 1; i < fg->wlen; i++) \ { \ int k = fg->wlen - i; \ hashtable_put(fg->qsBc_table, &fg->wpattern[i], &k); \ DPRINT(("BC shift for wide char %lc is %d\n", fg->wpattern[i], \ fg->wlen - i)); \ if (fg->icase) \ { \ tre_char_t wc = iswlower(fg->wpattern[i]) ? \ towupper(fg->wpattern[i]) : towlower(fg->wpattern[i]); \ hashtable_put(fg->qsBc_table, &wc, &k); \ } \ } /* * Fills in the good suffix table for SB/MB strings. */ #define FILL_BMGS \ if (!fg->hasdot) \ { \ fg->sbmGs = xmalloc(fg->len * sizeof(int)); \ if (!fg->sbmGs) \ return REG_ESPACE; \ _FILL_BMGS(fg->sbmGs, fg->pattern, fg->len, false); \ } /* * Fills in the good suffix table for wide strings. */ #define FILL_BMGS_WIDE \ if (!fg->hasdot) \ { \ fg->bmGs = xmalloc(fg->wlen * sizeof(int)); \ if (!fg->bmGs) \ return REG_ESPACE; \ _FILL_BMGS(fg->bmGs, fg->wpattern, fg->wlen, true); \ } #define _FILL_BMGS(arr, pat, plen, wide) \ { \ char *p; \ tre_char_t *wp; \ \ if (wide) \ { \ if (fg->icase) \ { \ wp = xmalloc(plen * sizeof(tre_char_t)); \ if (wp == NULL) \ return REG_ESPACE; \ for (int i = 0; i < plen; i++) \ wp[i] = towlower(pat[i]); \ _CALC_BMGS(arr, wp, plen); \ xfree(wp); \ } \ else \ _CALC_BMGS(arr, pat, plen); \ } \ else \ { \ if (fg->icase) \ { \ p = xmalloc(plen); \ if (p == NULL) \ return REG_ESPACE; \ for (int i = 0; i < plen; i++) \ p[i] = tolower(pat[i]); \ _CALC_BMGS(arr, p, plen); \ xfree(p); \ } \ else \ _CALC_BMGS(arr, pat, plen); \ } \ } #define _CALC_BMGS(arr, pat, plen) \ { \ int f, g; \ \ int *suff = xmalloc(plen * sizeof(int)); \ if (suff == NULL) \ return REG_ESPACE; \ \ suff[plen - 1] = plen; \ g = plen - 1; \ for (int i = plen - 2; i >= 0; i--) \ { \ if (i > g && suff[i + plen - 1 - f] < i - g) \ suff[i] = suff[i + plen - 1 - f]; \ else \ { \ if (i < g) \ g = i; \ f = i; \ while (g >= 0 && pat[g] == pat[g + plen - 1 - f]) \ g--; \ suff[i] = f - g; \ } \ } \ \ for (int i = 0; i < plen; i++) \ arr[i] = plen; \ g = 0; \ for (int i = plen - 1; i >= 0; i--) \ if (suff[i] == i + 1) \ for(; g < plen - 1 - i; g++) \ if (arr[g] == plen) \ arr[g] = plen - 1 - i; \ for (int i = 0; i <= plen - 2; i++) \ arr[plen - 1 - suff[i]] = plen - 1 - i; \ \ xfree(suff); \ } /* * Copies the pattern pat having lenght n to p and stores * the size in l. */ #define SAVE_PATTERN(p, l) \ l = (n == 0) ? tre_strlen(pat) : n; \ p = xmalloc((l + 1) * sizeof(tre_char_t)); \ if (p == NULL) \ return REG_ESPACE; \ memcpy(p, pat, l * sizeof(tre_char_t)); \ p[l] = TRE_CHAR('\0'); /* * Initializes pattern compiling. */ #define INIT_COMP \ /* Initialize. */ \ memset(fg, 0, sizeof(*fg)); \ fg->icase = (cflags & REG_ICASE); \ fg->word = (cflags & REG_WORD); \ fg->newline = (cflags & REG_NEWLINE); \ \ /* Cannot handle REG_ICASE with MB string */ \ if (fg->icase && (TRE_MB_CUR_MAX > 1)) \ return REG_BADPAT; \ \ /* Calculate length if unspecified */ \ n = (n == 0) ? tre_strlen(pat) : n; /* * Returns: REG_OK on success, error code otherwise */ int tre_compile_literal(fastmatch_t *fg, const tre_char_t *pat, size_t n, int cflags) { INIT_COMP; /* Cannot handle word boundaries with MB string */ if (fg->word && (TRE_MB_CUR_MAX > 1)) return REG_BADPAT; #ifdef TRE_WCHAR SAVE_PATTERN(fg->wpattern, fg->wlen); STORE_MBS_PAT; #else SAVE_PATTERN(fg->pattern, fg->len); #endif DPRINT(("tre_compile_literal: pattern: %s, icase: %c, word: %c, " "newline %c\n", fg->pattern, fg->icase ? 'y' : 'n', fg->word ? 'y' : 'n', fg->newline ? 'y' : 'n')); FILL_QSBC; FILL_BMGS; #ifdef TRE_WCHAR FILL_QSBC_WIDE; FILL_BMGS_WIDE; #endif return REG_OK; } /* * Returns: REG_OK on success, error code otherwise */ int tre_compile_fast(fastmatch_t *fg, const tre_char_t *pat, size_t n, int cflags) { INIT_COMP; /* Remove end-of-line character ('$'). */ if ((n > 0) && (pat[n - 1] == TRE_CHAR('$'))) { fg->eol = true; n--; } /* Remove beginning-of-line character ('^'). */ if (pat[0] == TRE_CHAR('^')) { fg->bol = true; n--; pat++; } /* Handle word-boundary matching when GNU extensions are enabled */ if ((cflags & REG_GNU) && (n >= 14) && (memcmp(pat, TRE_CHAR("[[:<:]]"), 7 * sizeof(tre_char_t)) == 0) && (memcmp(pat + n - 7, TRE_CHAR("[[:>:]]"), 7 * sizeof(tre_char_t)) == 0)) { n -= 14; pat += 7; fg->word = true; } /* Cannot handle word boundaries with MB string */ if (fg->word && (TRE_MB_CUR_MAX > 1)) return REG_BADPAT; /* Look for ways to cheat...er...avoid the full regex engine. */ for (unsigned int i = 0; i < n; i++) { /* Can still cheat? */ if (!(cflags & _REG_HEUR) && ((tre_isalnum(pat[i])) || tre_isspace(pat[i]) || (pat[i] == TRE_CHAR('_')) || (pat[i] == TRE_CHAR(',')) || (pat[i] == TRE_CHAR('=')) || (pat[i] == TRE_CHAR('-')) || (pat[i] == TRE_CHAR(':')) || (pat[i] == TRE_CHAR('/')))) continue; else if (pat[i] == TRE_CHAR('.')) fg->hasdot = i; else return REG_BADPAT; } /* * pat has been adjusted earlier to not include '^', '$' or * the word match character classes at the beginning and ending * of the string respectively. */ #ifdef TRE_WCHAR SAVE_PATTERN(fg->wpattern, fg->wlen); STORE_MBS_PAT; #else SAVE_PATTERN(fg->pattern, fg->len); #endif DPRINT(("tre_compile_fast: pattern: %s, bol %c, eol %c, " "icase: %c, word: %c, newline %c\n", fg->pattern, fg->bol ? 'y' : 'n', fg->eol ? 'y' : 'n', fg->icase ? 'y' : 'n', fg->word ? 'y' : 'n', fg->newline ? 'y' : 'n')); FILL_QSBC; FILL_BMGS; #ifdef TRE_WCHAR FILL_QSBC_WIDE; FILL_BMGS_WIDE; #endif return REG_OK; } #define _SHIFT_ONE \ { \ shift = 1; \ j += shift; \ continue; \ } #define _BBOUND_COND \ ((type == STR_WIDE) ? \ ((j == 0) || !(tre_isalnum(str_wide[j - 1]) || \ (str_wide[j - 1] == TRE_CHAR('_')))) : \ ((j == 0) || !(tre_isalnum(str_byte[j - 1]) || \ (str_byte[j - 1] == '_')))) #define _EBOUND_COND \ ((type == STR_WIDE) ? \ ((j + fg->wlen == len) || !(tre_isalnum(str_wide[j + fg->wlen]) || \ (str_wide[j + fg->wlen] == TRE_CHAR('_')))) : \ ((j + fg->len == len) || !(tre_isalnum(str_byte[j + fg->len]) || \ (str_byte[j + fg->len] == '_')))) /* * Condition to check whether the match on position j is on a * word boundary. */ #define IS_ON_WORD_BOUNDARY \ (_BBOUND_COND && _EBOUND_COND) /* * Checks word boundary and shifts one if match is not on a * boundary. */ #define CHECK_WORD_BOUNDARY \ if (!IS_ON_WORD_BOUNDARY) \ _SHIFT_ONE; #define _BOL_COND \ ((j == 0) || ((type == STR_WIDE) ? tre_isspace(str_wide[j - 1]) : \ isspace(str_byte[j - 1]))) /* * Checks BOL anchor and shifts one if match is not on a * boundary. */ #define CHECK_BOL_ANCHOR \ if (!_BOL_COND) \ _SHIFT_ONE; #define _EOL_COND \ ((type == STR_WIDE) ? \ ((j + fg->wlen == len) || tre_isspace(str_wide[j + fg->wlen])) : \ ((j + fg->len == len) || isspace(str_byte[j + fg->wlen]))) /* * Checks EOL anchor and shifts one if match is not on a * boundary. */ #define CHECK_EOL_ANCHOR \ if (!_EOL_COND) \ _SHIFT_ONE; /* * Executes matching of the precompiled pattern on the input string. * Returns REG_OK or REG_NOMATCH depending on if we find a match or not. */ int tre_match_fast(const fastmatch_t *fg, const void *data, size_t len, tre_str_type_t type, int nmatch, regmatch_t pmatch[], int eflags) { unsigned int j = 0; int ret = REG_NOMATCH; int mismatch, shift, u = 0, v; const char *str_byte = data; const void *startptr = NULL; const tre_char_t *str_wide = data; /* Calculate length if unspecified. */ if (len == (unsigned)-1) switch (type) { case STR_WIDE: len = tre_strlen(str_wide); break; default: len = strlen(str_byte); break; } /* No point in going farther if we do not have enough data. */ switch (type) { case STR_WIDE: if (len < fg->wlen) return ret; shift = fg->wlen; break; default: if (len < fg->len) return ret; shift = fg->len; } /* * REG_NOTBOL means not anchoring ^ to the beginning of the line, so we * can shift one because there can't be a match at the beginning. */ if (fg->bol && (eflags & REG_NOTBOL)) j = 1; /* * Like above, we cannot have a match at the very end when anchoring to * the end and REG_NOTEOL is specified. */ if (fg->eol && (eflags & REG_NOTEOL)) len--; /* Only try once at the beginning or ending of the line. */ if ((fg->bol || fg->eol) && !fg->newline && !(eflags & REG_NOTBOL) && !(eflags & REG_NOTEOL)) { /* Simple text comparison. */ if (!((fg->bol && fg->eol) && (type == STR_WIDE ? (len != fg->wlen) : (len != fg->len)))) { /* Determine where in data to start search at. */ j = fg->eol ? len - (type == STR_WIDE ? fg->wlen : fg->len) : 0; SKIP_CHARS(j); COMPARE; if (mismatch == REG_OK) { if (fg->word && !IS_ON_WORD_BOUNDARY) return ret; pmatch[0].rm_so = j; pmatch[0].rm_eo = j + (type == STR_WIDE ? fg->wlen : fg->len); return REG_OK; } } } else { /* Quick Search / Turbo Boyer-Moore algorithm. */ do { SKIP_CHARS(j); COMPARE; if (mismatch == REG_OK) { if (fg->word) CHECK_WORD_BOUNDARY; if (fg->bol) CHECK_BOL_ANCHOR; if (fg->eol) CHECK_EOL_ANCHOR; pmatch[0].rm_so = j; pmatch[0].rm_eo = j + ((type == STR_WIDE) ? fg->wlen : fg->len); return REG_OK; } else if (mismatch > 0) return mismatch; mismatch = -mismatch - 1; SHIFT; } while (!IS_OUT_OF_BOUNDS); } return ret; } /* * Frees the resources that were allocated when the pattern was compiled. */ void tre_free_fast(fastmatch_t *fg) { DPRINT(("tre_fast_free: freeing structures for pattern %s\n", fg->pattern)); #ifdef TRE_WCHAR hashtable_free(fg->qsBc_table); if (!fg->hasdot) xfree(fg->bmGs); xfree(fg->wpattern); #endif if (!fg->hasdot) xfree(fg->sbmGs); xfree(fg->pattern); } /* * Returns: -(i + 1) on failure (position that it failed with minus sign) * error code on error * REG_OK on success */ static inline int fastcmp(const void *pat, const void *data, size_t len, tre_str_type_t type, bool icase, bool newline) { const char *str_byte = data; const char *pat_byte = pat; int ret = REG_OK; const tre_char_t *str_wide = data; const tre_char_t *pat_wide = pat; /* Compare the pattern and the input char-by-char from the last position. */ for (int i = len - 1; i >= 0; i--) { switch (type) { case STR_WIDE: /* Check dot */ if (pat_wide[i] == TRE_CHAR('.') && (!newline || (str_wide[i] != TRE_CHAR('\n')))) continue; /* Compare */ if (icase ? (towlower(pat_wide[i]) == towlower(str_wide[i])) : (pat_wide[i] == str_wide[i])) continue; break; default: /* Check dot */ if (pat_byte[i] == '.' && (!newline || (str_byte[i] != '\n'))) continue; /* Compare */ if (icase ? (tolower(pat_byte[i]) == tolower(str_byte[i])) : (pat_byte[i] == str_byte[i])) continue; } DPRINT(("fastcmp: mismatch at position %d\n", i)); ret = -(i + 1); break; } return ret; } Index: user/gabor/tre-integration/contrib/tre/lib/tre-fastmatch.h =================================================================== --- user/gabor/tre-integration/contrib/tre/lib/tre-fastmatch.h (revision 225155) +++ user/gabor/tre-integration/contrib/tre/lib/tre-fastmatch.h (revision 225156) @@ -1,20 +1,19 @@ #ifndef TRE_FASTMATCH_H #define TRE_FASTMATCH_H 1 #include -#include #include #include #include #include "hashtable.h" #include "tre-internal.h" int tre_compile_literal(fastmatch_t *preg, const tre_char_t *regex, size_t, int); int tre_compile_fast(fastmatch_t *preg, const tre_char_t *regex, size_t, int); int tre_match_fast(const fastmatch_t *fg, const void *data, size_t len, tre_str_type_t type, int nmatch, regmatch_t pmatch[], int eflags); void tre_free_fast(fastmatch_t *preg); #endif /* TRE_FASTMATCH_H */ Index: user/gabor/tre-integration/include/hashtable.h =================================================================== --- user/gabor/tre-integration/include/hashtable.h (revision 225155) +++ user/gabor/tre-integration/include/hashtable.h (nonexistent) @@ -1,27 +0,0 @@ -/* $FreeBSD$ */ - -#ifndef HASHTABLE_H -#define HASHTABLE_H 1 - -#include - -typedef struct { - void *key; - void *value; -} hashtable_entry; - -typedef struct { - size_t key_size; - size_t table_size; - size_t usage; - size_t value_size; - hashtable_entry **entries; -} hashtable; - -void hashtable_free(hashtable *); -int hashtable_get(hashtable *, const void *, void *); -hashtable *hashtable_init(size_t, size_t, size_t); -int hashtable_put(hashtable *, const void *, const void *); -int hashtable_remove(hashtable *, const void *); - -#endif /* HASHTABLE.H */ Property changes on: user/gabor/tre-integration/include/hashtable.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: user/gabor/tre-integration/include/Makefile =================================================================== --- user/gabor/tre-integration/include/Makefile (revision 225155) +++ user/gabor/tre-integration/include/Makefile (revision 225156) @@ -1,317 +1,317 @@ # @(#)Makefile 8.2 (Berkeley) 1/4/94 # $FreeBSD$ # # Doing a "make install" builds /usr/include. .include CLEANFILES= osreldate.h version vers.c SUBDIR= arpa gssapi protocols rpcsvc rpc INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h _ctype.h ctype.h \ db.h \ dirent.h dlfcn.h elf.h elf-hints.h err.h fastmatch.h fmtmsg.h fnmatch.h \ fstab.h fts.h ftw.h getopt.h glob.h grp.h gssapi.h \ - hashtable.h ieeefp.h ifaddrs.h \ + ieeefp.h ifaddrs.h \ inttypes.h iso646.h kenv.h langinfo.h libgen.h limits.h link.h \ locale.h malloc.h malloc_np.h memory.h monetary.h mpool.h mqueue.h \ ndbm.h netconfig.h \ netdb.h nl_types.h nlist.h nss.h nsswitch.h paths.h \ printf.h proc_service.h pthread.h \ pthread_np.h pwd.h ranlib.h readpassphrase.h regex.h \ res_update.h resolv.h runetype.h search.h semaphore.h setjmp.h \ signal.h spawn.h stab.h \ stdbool.h stddef.h stdio.h stdlib.h string.h stringlist.h \ strings.h sysexits.h tar.h termios.h tgmath.h \ time.h timeconv.h timers.h ttyent.h \ ulimit.h unistd.h utime.h utmpx.h uuid.h varargs.h vis.h \ wchar.h wctype.h wordexp.h MHDRS= float.h floatingpoint.h stdarg.h PHDRS= sched.h _semaphore.h LHDRS= aio.h errno.h fcntl.h linker_set.h poll.h stdint.h syslog.h \ ucontext.h LDIRS= bsm cam geom net net80211 netatalk netgraph netinet netinet6 \ netipsec ${_netipx} netnatm ${_netncp} netsmb \ nfs nfsclient nfsserver \ sys vm LSUBDIRS= cam/ata cam/scsi \ dev/acpica dev/an dev/bktr dev/firewire dev/hwpmc \ dev/ic dev/iicbus ${_dev_ieee488} dev/io dev/lmc dev/mfi dev/ofw \ dev/pbio ${_dev_powermac_nvram} dev/ppbus dev/smbus \ dev/speaker dev/usb dev/utopia dev/vkbd dev/wi \ fs/devfs fs/fdescfs fs/fifofs fs/msdosfs fs/nfs fs/ntfs fs/nullfs \ ${_fs_nwfs} fs/portalfs fs/procfs fs/smbfs fs/udf fs/unionfs \ geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \ geom/mirror geom/mountver geom/multipath geom/nop \ geom/raid geom/raid3 geom/shsec geom/stripe geom/virstor \ netgraph/atm netgraph/netflow \ security/audit \ security/mac_biba security/mac_bsdextended security/mac_lomac \ security/mac_mls security/mac_partition \ ufs/ffs ufs/ufs LSUBSUBDIRS= dev/mpt/mpilib .if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "powerpc64" _dev_powermac_nvram= dev/powermac_nvram .endif .if ${MK_GPIB} != "no" _dev_ieee488= dev/ieee488 .endif .if ${MK_HESIOD} != "no" INCS+= hesiod.h .endif .if ${MK_ICONV} != "no" INCS+= iconv.h .endif .if ${MK_BLUETOOTH} != "no" LSUBSUBDIRS+= netgraph/bluetooth/include .endif # XXX unconditionally needed by #.if ${MK_IPX} != "no" _netipx= netipx #.endif .if ${MK_NCP} != "no" _netncp= netncp _fs_nwfs= fs/nwfs .endif # Define SHARED to indicate whether you want symbolic links to the system # source (``symlinks''), or a separate copy (``copies''). ``symlinks'' is # probably only useful for developers and should be avoided if you do not # wish to tie your /usr/include and /usr/src together. #SHARED= symlinks SHARED?= copies INCS+= osreldate.h osreldate.h: ${.CURDIR}/../sys/conf/newvers.sh ${.CURDIR}/../sys/sys/param.h \ ${.CURDIR}/Makefile @${ECHO} creating osreldate.h from newvers.sh @MAKE=${MAKE}; \ PARAMFILE=${.CURDIR}/../sys/sys/param.h; \ . ${.CURDIR}/../sys/conf/newvers.sh; \ echo "$$COPYRIGHT" > osreldate.h; \ echo "#ifdef _KERNEL" >> osreldate.h; \ echo "#error \" cannot be used in the kernel, use \"" >> osreldate.h; \ echo "#else" >> osreldate.h; \ echo "#undef __FreeBSD_version" >> osreldate.h; \ echo "#define __FreeBSD_version $$RELDATE" >> osreldate.h; \ echo "#endif" >> osreldate.h .for i in ${LHDRS} INCSLINKS+= sys/$i ${INCLUDEDIR}/$i .endfor .for i in ${MHDRS} INCSLINKS+= machine/$i ${INCLUDEDIR}/$i .endfor .for i in ${PHDRS} INCSLINKS+= sys/$i ${INCLUDEDIR}/$i .endfor .if ${MACHINE} != ${MACHINE_CPUARCH} _MARCHS= ${MACHINE_CPUARCH} .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" _MARCHS+= x86 .endif .include installincludes: ${SHARED} ${SHARED}: compat # Take care of stale directory-level symlinks. compat: .for i in ${LDIRS} ${LSUBDIRS} machine ${_MARCHS} crypto if [ -L ${DESTDIR}${INCLUDEDIR}/$i ]; then \ rm -f ${DESTDIR}${INCLUDEDIR}/$i; \ fi .endfor mtree -deU ${MTREE_FOLLOWS_SYMLINKS} \ -f ${.CURDIR}/../etc/mtree/BSD.include.dist \ -p ${DESTDIR}${INCLUDEDIR} .if ${MK_BIND_LIBS} != "no" mtree -deU ${MTREE_FOLLOWS_SYMLINKS} \ -f ${.CURDIR}/../etc/mtree/BIND.include.dist \ -p ${DESTDIR}${INCLUDEDIR} .endif copies: .for i in ${LDIRS} ${LSUBDIRS} ${LSUBSUBDIRS} altq crypto machine machine/pc \ ${_MARCHS} .if exists(${DESTDIR}${INCLUDEDIR}/$i) cd ${DESTDIR}${INCLUDEDIR}/$i; \ for h in *.h; do \ if [ -L $$h ]; then rm -f $$h; fi; \ done .endif .endfor .for i in ${LDIRS} ${LSUBDIRS:Ndev/acpica:Ndev/bktr} ${LSUBSUBDIRS} cd ${.CURDIR}/../sys; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \ ${DESTDIR}${INCLUDEDIR}/$i .endfor cd ${.CURDIR}/../sys/dev/acpica; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 acpiio.h \ ${DESTDIR}${INCLUDEDIR}/dev/acpica cd ${.CURDIR}/../sys/dev/bktr; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ioctl_*.h \ ${DESTDIR}${INCLUDEDIR}/dev/bktr cd ${.CURDIR}/../sys/contrib/altq/altq; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/altq cd ${.CURDIR}/../sys/fs/cd9660/; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/isofs/cd9660 .if ${MK_IPFILTER} != "no" cd ${.CURDIR}/../sys/contrib/ipfilter/netinet; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/netinet .endif cd ${.CURDIR}/../sys/contrib/pf/net; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/net cd ${.CURDIR}/../sys/crypto; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 rijndael/rijndael.h \ ${DESTDIR}${INCLUDEDIR}/crypto cd ${.CURDIR}/../sys/opencrypto; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/crypto cd ${.CURDIR}/../sys/${MACHINE}/include; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/machine .if exists(${.CURDIR}/../sys/${MACHINE}/include/pc) cd ${.CURDIR}/../sys/${MACHINE}/include/pc; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/machine/pc .endif .for _MARCH in ${_MARCHS} .if exists(${.CURDIR}/../sys/${_MARCH}/include) ${INSTALL} -d -o ${BINOWN} -g ${BINGRP} -m 755 \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}; \ cd ${.CURDIR}/../sys/${_MARCH}/include; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/${_MARCH} .if exists(${.CURDIR}/../sys/${_MARCH}/include/pc) ${INSTALL} -d -o ${BINOWN} -g ${BINGRP} -m 755 \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}/pc; \ cd ${.CURDIR}/../sys/${_MARCH}/include/pc; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}/pc .endif .endif .endfor cd ${.CURDIR}/../sys/rpc; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 types.h \ ${DESTDIR}${INCLUDEDIR}/rpc symlinks: @${ECHO} "Setting up symlinks to kernel source tree..." .for i in ${LDIRS} cd ${.CURDIR}/../sys/$i; \ for h in *.h; do \ ln -fs ../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \ done .endfor .for i in ${LSUBDIRS:Ndev/acpica:Ndev/bktr} cd ${.CURDIR}/../sys/$i; \ for h in *.h; do \ ln -fs ../../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \ done .endfor cd ${.CURDIR}/../sys/dev/acpica; \ for h in acpiio.h; do \ ln -fs ../../../../sys/dev/acpica/$$h \ ${DESTDIR}${INCLUDEDIR}/dev/acpica; \ done cd ${.CURDIR}/../sys/dev/bktr; \ for h in ioctl_*.h; do \ ln -fs ../../../../sys/dev/bktr/$$h \ ${DESTDIR}${INCLUDEDIR}/dev/bktr; \ done .for i in ${LSUBSUBDIRS} cd ${.CURDIR}/../sys/$i; \ for h in *.h; do \ ln -fs ../../../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \ done .endfor cd ${.CURDIR}/../sys/contrib/altq/altq; \ for h in *.h; do \ ln -fs ../../../sys/contrib/altq/altq/$$h \ ${DESTDIR}${INCLUDEDIR}/altq; \ done .if ${MK_IPFILTER} != "no" cd ${.CURDIR}/../sys/contrib/ipfilter/netinet; \ for h in *.h; do \ ln -fs ../../../sys/contrib/ipfilter/netinet/$$h \ ${DESTDIR}${INCLUDEDIR}/netinet; \ done .endif cd ${.CURDIR}/../sys/contrib/pf/net; \ for h in *.h; do \ ln -fs ../../../sys/contrib/pf/net/$$h \ ${DESTDIR}${INCLUDEDIR}/net; \ done cd ${.CURDIR}/../sys/crypto; \ for h in rijndael/rijndael.h; do \ ln -fs ../../../sys/crypto/$$h \ ${DESTDIR}${INCLUDEDIR}/crypto; \ done cd ${.CURDIR}/../sys/opencrypto; \ for h in *.h; do \ ln -fs ../../../sys/opencrypto/$$h \ ${DESTDIR}${INCLUDEDIR}/crypto; \ done cd ${.CURDIR}/../sys/${MACHINE}/include; \ for h in *.h; do \ ln -fs ../../../sys/${MACHINE}/include/$$h \ ${DESTDIR}${INCLUDEDIR}/machine; \ done .if exists(${.CURDIR}/../sys/${MACHINE}/include/pc) cd ${.CURDIR}/../sys/${MACHINE}/include/pc; \ for h in *.h; do \ ln -fs ../../../../sys/${MACHINE}/include/pc/$$h \ ${DESTDIR}${INCLUDEDIR}/machine/pc; \ done .endif .for _MARCH in ${_MARCHS} .if exists(${.CURDIR}/../sys/${_MARCH}/include) ${INSTALL} -d -o ${BINOWN} -g ${BINGRP} -m 755 \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}; \ cd ${.CURDIR}/../sys/${_MARCH}/include; \ for h in *.h; do \ ln -fs ../../../sys/${_MARCH}/include/$$h \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}; \ done .if exists(${.CURDIR}/../sys/${_MARCH}/include/pc) ${INSTALL} -d -o ${BINOWN} -g ${BINGRP} -m 755 \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}/pc; \ cd ${.CURDIR}/../sys/${_MARCH}/include/pc; \ for h in *.h; do \ ln -fs ../../../../sys/${_MARCH}/include/pc/$$h \ ${DESTDIR}${INCLUDEDIR}/${_MARCH}/pc; \ done .endif .endif .endfor cd ${.CURDIR}/../sys/fs/cd9660; \ for h in *.h; do \ ln -fs ../../../../sys/fs/cd9660/$$h \ ${DESTDIR}${INCLUDEDIR}/isofs/cd9660; \ done cd ${.CURDIR}/../sys/rpc; \ for h in types.h; do \ ln -fs ../../../sys/rpc/$$h \ ${DESTDIR}${INCLUDEDIR}/rpc; \ done Index: user/gabor/tre-integration/include/fastmatch.h =================================================================== --- user/gabor/tre-integration/include/fastmatch.h (revision 225155) +++ user/gabor/tre-integration/include/fastmatch.h (revision 225156) @@ -1,78 +1,77 @@ /* $FreeBSD$ */ #ifndef FASTMATCH_H #define FASTMATCH_H 1 -#include #include #include #include #include typedef struct { size_t wlen; size_t len; wchar_t *wpattern; int hasdot; int qsBc[UCHAR_MAX + 1]; int *bmGs; char *pattern; int defBc; - hashtable *qsBc_table; + void *qsBc_table; int *sbmGs; const char *re_endp; /* flags */ bool bol; bool eol; bool word; bool icase; bool newline; } fastmatch_t; extern int tre_fixcomp(fastmatch_t *preg, const char *regex, int cflags); extern int tre_fastcomp(fastmatch_t *preg, const char *regex, int cflags); extern int tre_fastexec(const fastmatch_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); extern void tre_fastfree(fastmatch_t *preg); extern int tre_fixwcomp(fastmatch_t *preg, const wchar_t *regex, int cflags); extern int tre_fastwcomp(fastmatch_t *preg, const wchar_t *regex, int cflags); extern int tre_fastwexec(const fastmatch_t *preg, const wchar_t *string, size_t nmatch, regmatch_t pmatch[], int eflags); /* Versions with a maximum length argument and therefore the capability to handle null characters in the middle of the strings. */ extern int tre_fixncomp(fastmatch_t *preg, const char *regex, size_t len, int cflags); extern int tre_fastncomp(fastmatch_t *preg, const char *regex, size_t len, int cflags); extern int tre_fastnexec(const fastmatch_t *preg, const char *string, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags); extern int tre_fixwncomp(fastmatch_t *preg, const wchar_t *regex, size_t len, int cflags); extern int tre_fastwncomp(fastmatch_t *preg, const wchar_t *regex, size_t len, int cflags); extern int tre_fastwnexec(const fastmatch_t *preg, const wchar_t *string, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags); #endif /* FASTMATCH_H */