Index: user/gabor/tre-integration/contrib/tre/lib/fastmatch.c =================================================================== --- user/gabor/tre-integration/contrib/tre/lib/fastmatch.c (revision 223736) +++ user/gabor/tre-integration/contrib/tre/lib/fastmatch.c (revision 223737) @@ -1,453 +1,493 @@ /*- * 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 #include "fastmatch.h" #include "hashtable.h" #include "tre.h" #include "tre-internal.h" #include "xmalloc.h" static int fastcmp(const tre_char_t *, const void *, size_t, tre_str_type_t); static void revstr(tre_char_t *, int); #ifdef TRE_WCHAR #define TRE_CHAR(n) L##n #else #define TRE_CHAR(n) n #endif #define SKIP_CHARS(n) \ do { \ switch (type) \ { \ case STR_BYTE: \ startptr = str_byte + n; \ break; \ case STR_MBS: \ for (skip = j = 0; j < n; j++) \ { \ siz = mbrlen(str_byte, MB_CUR_MAX, NULL); \ skip += siz; \ } \ startptr = str_byte + skip; \ break; \ case STR_WIDE: \ startptr = str_wide + n; \ break; \ default: \ /* XXX */ \ break; \ } \ } while (0); \ /* * Returns: -1 on failure, 0 on success */ int tre_fastcomp_literal(fastmatch_t *fg, const tre_char_t *pat, size_t n, int cflags) { /* Initialize. */ fg->len = (n == 0) ? tre_strlen(pat) : n; fg->bol = false; fg->eol = false; fg->reversed = false; fg->cflags = cflags; fg->pattern = xmalloc((fg->len + 1) * sizeof(tre_char_t)); if (fg->pattern == NULL) return -1; memcpy(fg->pattern, pat, fg->len * sizeof(tre_char_t)); fg->pattern[fg->len] = TRE_CHAR('\0'); /* Preprocess pattern. */ #ifdef TRE_WCHAR fg->defBc = fg->len; fg->qsBc = hashtable_init(fg->len, sizeof(tre_char_t), sizeof(int)); if (fg->qsBc == NULL) return -1; for (unsigned int i = 1; i < fg->len; i++) { int k = fg->len - i; hashtable_put(fg->qsBc, &fg->pattern[i], &k); } #else for (i = 0; i <= UCHAR_MAX; i++) fg->qsBc[i] = fg->len; for (i = 1; i < fg->len; i++) fg->qsBc[fg->pattern[i]] = fg->len - i; #endif return REG_OK; } /* * Returns: -1 on failure, 0 on success */ int tre_fastcomp(fastmatch_t *fg, const tre_char_t *pat, size_t n, int cflags) { int firstHalfDot = -1; int firstLastHalfDot = -1; int hasDot = 0; int lastHalfDot = 0; /* Initialize. */ fg->len = (n == 0) ? tre_strlen(pat) : n; fg->bol = false; fg->eol = false; fg->reversed = false; fg->word = false; fg->cflags = cflags; /* Remove end-of-line character ('$'). */ if ((fg->len > 0) && (pat[fg->len - 1] == TRE_CHAR('$'))) { fg->eol = true; fg->len--; } /* Remove beginning-of-line character ('^'). */ if (pat[0] == TRE_CHAR('^')) { fg->bol = true; fg->len--; pat++; } if ((fg->len >= 14) && (memcmp(pat, TRE_CHAR("[[:<:]]"), 7 * sizeof(tre_char_t)) == 0) && (memcmp(pat + fg->len - 7, TRE_CHAR("[[:>:]]"), 7 * sizeof(tre_char_t)) == 0)) { fg->len -= 14; pat += 7; fg->word = true; } /* * pat has been adjusted earlier to not include '^', '$' or * the word match character classes at the beginning and ending * of the string respectively. */ fg->pattern = xmalloc((fg->len + 1) * sizeof(tre_char_t)); memcpy(fg->pattern, pat, fg->len * sizeof(tre_char_t)); fg->pattern[fg->len] = TRE_CHAR('\0'); /* Look for ways to cheat...er...avoid the full regex engine. */ for (unsigned int i = 0; i < fg->len; i++) { /* Can still cheat? */ #ifdef TRE_WCHAR if ((iswalnum(fg->pattern[i])) || iswspace(fg->pattern[i]) || #else if ((isalnum(fg->pattern[i])) || isspace(fg->pattern[i]) || #endif (fg->pattern[i] == TRE_CHAR('_')) || (fg->pattern[i] == TRE_CHAR(',')) || (fg->pattern[i] == TRE_CHAR('=')) || (fg->pattern[i] == TRE_CHAR('-')) || (fg->pattern[i] == TRE_CHAR(':')) || (fg->pattern[i] == TRE_CHAR('/'))) { continue; } else if (fg->pattern[i] == TRE_CHAR('\0')) { hasDot = i; if (i < fg->len / 2) { if (firstHalfDot < 0) /* Closest dot to the beginning */ firstHalfDot = i; } else { /* Closest dot to the end of the pattern. */ lastHalfDot = i; if (firstLastHalfDot < 0) firstLastHalfDot = i; } } else { /* Free memory and let others know this is empty. */ free(fg->pattern); fg->pattern = NULL; return -1; } } /* * Determine if a reverse search would be faster based on the placement * of the dots. */ if ((!(fg->bol || fg->eol)) && (lastHalfDot && ((firstHalfDot < 0) || ((fg->len - (lastHalfDot + 1)) < (size_t)firstHalfDot)))) { fg->reversed = true; hasDot = fg->len - (firstHalfDot < 0 ? firstLastHalfDot : firstHalfDot) - 1; revstr(fg->pattern, fg->len); } /* * 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. A * reverse version of this algorithm would be useful for wildcards near * the end of the string. * * Examples: * Pattern Max shift * ------- --------- * this 5 * .his 4 * t.is 3 * th.s 2 * thi. 1 */ #ifdef TRE_WCHAR /* Adjust the shift based on location of the last dot ('.'). */ fg->defBc = fg->len - hasDot; /* Preprocess pattern. */ fg->qsBc = hashtable_init(fg->len, sizeof(tre_char_t), sizeof(int)); for (unsigned int i = hasDot + 1; i < fg->len; i++) { int k = fg->len - i; hashtable_put(fg->qsBc, &fg->pattern[i], &k); } #else /* Preprocess pattern. */ for (unsigned int i = 0; i <= (signed)UCHAR_MAX; i++) fg->qsBc[i] = fg->len - hasDot; for (unsigned int i = hasDot + 1; i < fg->len; i++) { fg->qsBc[fg->pattern[i]] = fg->len - i; } #endif /* * Put pattern back to normal after pre-processing to allow for easy * comparisons later. */ if (fg->reversed) revstr(fg->pattern, fg->len); return REG_OK; } int tre_fastexec(const fastmatch_t *fg, const void *data, size_t len, tre_str_type_t type, int nmatch, regmatch_t pmatch[]) { unsigned int j; size_t siz, skip; int cnt = 0; int ret = REG_NOMATCH; const char *str_byte = data; - const void *startptr; + const void *startptr = NULL; #ifdef TRE_WCHAR const wchar_t *str_wide = data; #endif if (len == (unsigned)-1) { switch (type) { case STR_BYTE: case STR_MBS: len = strlen(str_byte); break; case STR_WIDE: len = wcslen(str_wide); break; default: /* XXX */ break; } } /* No point in going farther if we do not have enough data. */ if (len < fg->len) return ret; /* Only try once at the beginning or ending of the line. */ if (fg->bol || fg->eol) { /* Simple text comparison. */ if (!((fg->bol && fg->eol) && (len != fg->len))) { /* Determine where in data to start search at. */ j = fg->eol ? len - fg->len : 0; SKIP_CHARS(j); if (fastcmp(fg->pattern, startptr, fg->len, type) == -1) { if (!(fg->cflags & REG_NOSUB) || (nmatch < 1)) return REG_OK; pmatch[cnt].rm_so = j; pmatch[cnt].rm_eo = j + fg->len; return REG_OK; } } } else if (fg->reversed) { /* Quick Search algorithm. */ j = len; do { SKIP_CHARS(j - fg->len); if (fastcmp(fg->pattern, startptr, fg->len, type) == -1) { if (!(fg->cflags & REG_NOSUB) || (nmatch < 1)) return REG_OK; pmatch[cnt++].rm_so = j - fg->len; pmatch[cnt++].rm_eo = j; nmatch--; ret = REG_OK; if (nmatch < 1) return ret; else { j -= 2 * fg->len; continue; } } /* Shift if within bounds, otherwise, we are done. */ if (((long)j - (long)fg->len - 1) < 0) break; #ifdef TRE_WCHAR { - int k, r; + int k, r = -1; + wint_t wc; + const char *ch; + const wchar_t *ws; - r = hashtable_get(fg->qsBc, &data[j - fg->len - 1], &k); + SKIP_CHARS(j - fg->len - 1); + switch (type) + { + case STR_BYTE: + case STR_MBS: + ch = startptr; + mbrtowc(&wc, ch, MB_CUR_MAX, NULL); + r = hashtable_get(fg->qsBc, &wc, &k); + break; + case STR_WIDE: + ws = startptr; + r = hashtable_get(fg->qsBc, ws, &k); + break; + default: + /* XXX */ + break; + } k = (r == 0) ? k : fg->defBc; - j -= k; + j += k; } #else - j -= fg->qsBc[data[j - fg->len - 1]]; + SKIP_CHARS(j - fg->len - 1); + j += fg->qsBc[startptr[0]]; #endif } while (j >= fg->len); } else { /* Quick Search algorithm. */ j = 0; do { SKIP_CHARS(j); if (fastcmp(fg->pattern, startptr, fg->len, type) == -1) { if (!(fg->cflags & REG_NOSUB) || (nmatch < 1)) return REG_OK; pmatch[cnt++].rm_so = j; pmatch[cnt++].rm_eo = j + fg->len; nmatch--; ret = REG_OK; if (nmatch < 1) return ret; else { j += fg->len; continue; } } /* Shift if within bounds, otherwise, we are done. */ if ((j + fg->len) >= len) break; #ifdef TRE_WCHAR { - int k, r; + int k, r = -1; + wint_t wc; + const char *ch; + const wchar_t *ws; - r = hashtable_get(fg->qsBc, &data[j + fg->len], &k); + SKIP_CHARS(j + fg->len); + switch (type) + { + case STR_BYTE: + case STR_MBS: + ch = startptr; + mbrtowc(&wc, ch, MB_CUR_MAX, NULL); + r = hashtable_get(fg->qsBc, &wc, &k); + break; + case STR_WIDE: + ws = startptr; + r = hashtable_get(fg->qsBc, ws, &k); + break; + default: + /* XXX */ + break; + } k = (r == 0) ? k : fg->defBc; j += k; } #else - j += fg->qsBc[data[j + fg->len]]; + SKIP_CHARS(j + fg->len); + j += fg->qsBc[startptr[0]]; #endif } while (j <= (len - fg->len)); } return ret; } void tre_fastfree(fastmatch_t *fg) { #ifdef TRE_WCHAR hashtable_free(fg->qsBc); #endif free(fg->pattern); } /* * Returns: i >= 0 on failure (position that it failed) * -1 on success */ static inline int fastcmp(const tre_char_t *pat, const void *data, size_t len, tre_str_type_t type) { const char *str_byte = data; #ifdef TRE_WCHAR const wchar_t *str_wide = data; wint_t wc; size_t s; #endif for (unsigned int i = 0; i < len; i++) { if (pat[i] == TRE_CHAR('.')) continue; switch (type) { case STR_BYTE: if (pat[i] == btowc(str_byte[i])) continue; break; case STR_MBS: s = mbrtowc(&wc, str_byte, MB_CUR_MAX, NULL); if (s == (size_t)-1) return i; else str_byte += s; if (pat[i] == wc) continue; break; case STR_WIDE: if (pat[i] == str_wide[i]) continue; break; default: /* XXX */ break; } return i; } return -1; } static inline void revstr(tre_char_t *str, int len) { tre_char_t c; for (int i = 0; i < len / 2; i++) { c = str[i]; str[i] = str[len - i - 1]; str[len - i - 1] = c; } } Index: user/gabor/tre-integration/contrib/tre/lib/regexec.c =================================================================== --- user/gabor/tre-integration/contrib/tre/lib/regexec.c (revision 223736) +++ user/gabor/tre-integration/contrib/tre/lib/regexec.c (revision 223737) @@ -1,409 +1,409 @@ /* tre_regexec.c - TRE POSIX compatible matching functions (and more). This software is released under a BSD-style license. See the file LICENSE for details and copyright. */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #ifdef TRE_USE_ALLOCA /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif #endif /* TRE_USE_ALLOCA */ #include #include #include #ifdef HAVE_WCHAR_H #include #endif /* HAVE_WCHAR_H */ #ifdef HAVE_WCTYPE_H #include #endif /* HAVE_WCTYPE_H */ #ifndef TRE_WCHAR #include #endif /* !TRE_WCHAR */ #ifdef HAVE_MALLOC_H #include #endif /* HAVE_MALLOC_H */ #include #include "fastmatch.h" #include "tre-internal.h" #include "tre.h" #include "xmalloc.h" #ifdef TRE_WEAK_REF __weak_reference(tre_regexec, regexec); __weak_reference(tre_regnexec, regnexec); __weak_reference(tre_regwexec, regwexec); __weak_reference(tre_regwnexec, regwnexec); __weak_reference(tre_reguexec, reguexec); __weak_reference(tre_regaexec, regaexec); __weak_reference(tre_reganexec, reganexec); __weak_reference(tre_regawexec, regawexec); __weak_reference(tre_regawnexec, regawnexec); #endif /* Fills the POSIX.2 regmatch_t array according to the TNFA tag and match endpoint values. */ void tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags, const tre_tnfa_t *tnfa, int *tags, int match_eo) { tre_submatch_data_t *submatch_data; unsigned int i, j; int *parents; i = 0; if (match_eo >= 0 && !(cflags & REG_NOSUB)) { /* Construct submatch offsets from the tags. */ DPRINT(("end tag = t%d = %d\n", tnfa->end_tag, match_eo)); submatch_data = tnfa->submatch_data; while (i < tnfa->num_submatches && i < nmatch) { if (submatch_data[i].so_tag == tnfa->end_tag) pmatch[i].rm_so = match_eo; else pmatch[i].rm_so = tags[submatch_data[i].so_tag]; if (submatch_data[i].eo_tag == tnfa->end_tag) pmatch[i].rm_eo = match_eo; else pmatch[i].rm_eo = tags[submatch_data[i].eo_tag]; /* If either of the endpoints were not used, this submatch was not part of the match. */ if (pmatch[i].rm_so == -1 || pmatch[i].rm_eo == -1) pmatch[i].rm_so = pmatch[i].rm_eo = -1; DPRINT(("pmatch[%d] = {t%d = %d, t%d = %d}\n", i, submatch_data[i].so_tag, pmatch[i].rm_so, submatch_data[i].eo_tag, pmatch[i].rm_eo)); i++; } /* Reset all submatches that are not within all of their parent submatches. */ i = 0; while (i < tnfa->num_submatches && i < nmatch) { if (pmatch[i].rm_eo == -1) assert(pmatch[i].rm_so == -1); assert(pmatch[i].rm_so <= pmatch[i].rm_eo); parents = submatch_data[i].parents; if (parents != NULL) for (j = 0; parents[j] >= 0; j++) { DPRINT(("pmatch[%d] parent %d\n", i, parents[j])); if (pmatch[i].rm_so < pmatch[parents[j]].rm_so || pmatch[i].rm_eo > pmatch[parents[j]].rm_eo) pmatch[i].rm_so = pmatch[i].rm_eo = -1; } i++; } } while (i < nmatch) { pmatch[i].rm_so = -1; pmatch[i].rm_eo = -1; i++; } } /* Wrapper functions for POSIX compatible regexp matching. */ int tre_have_backrefs(const regex_t *preg) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; return tnfa->have_backrefs; } int tre_have_approx(const regex_t *preg) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; return tnfa->have_approx; } static int tre_match(const tre_tnfa_t *tnfa, const void *string, size_t len, tre_str_type_t type, size_t nmatch, regmatch_t pmatch[], int eflags, fastmatch_t *shortcut) { reg_errcode_t status; int *tags = NULL, eo; /* Check if we can cheat with a fixed string */ if (shortcut != NULL) - return tre_fastexec(shortcut, string, len, nmatch, pmatch); + return tre_fastexec(shortcut, string, len, type, nmatch, pmatch); if (tnfa->num_tags > 0 && nmatch > 0) { #ifdef TRE_USE_ALLOCA tags = alloca(sizeof(*tags) * tnfa->num_tags); #else /* !TRE_USE_ALLOCA */ tags = xmalloc(sizeof(*tags) * tnfa->num_tags); #endif /* !TRE_USE_ALLOCA */ if (tags == NULL) return REG_ESPACE; } /* Dispatch to the appropriate matcher. */ if (tnfa->have_backrefs || eflags & REG_BACKTRACKING_MATCHER) { /* The regex has back references, use the backtracking matcher. */ if (type == STR_USER) { const tre_str_source *source = string; if (source->rewind == NULL || source->compare == NULL) /* The backtracking matcher requires rewind and compare capabilities from the input stream. */ return REG_BADPAT; } status = tre_tnfa_run_backtrack(tnfa, string, (int)len, type, tags, eflags, &eo); } #ifdef TRE_APPROX else if (tnfa->have_approx || eflags & REG_APPROX_MATCHER) { /* The regex uses approximate matching, use the approximate matcher. */ regamatch_t match; regaparams_t params; tre_regaparams_default(¶ms); params.max_err = 0; params.max_cost = 0; status = tre_tnfa_run_approx(tnfa, string, (int)len, type, tags, &match, params, eflags, &eo); } #endif /* TRE_APPROX */ else { /* Exact matching, no back references, use the parallel matcher. */ status = tre_tnfa_run_parallel(tnfa, string, (int)len, type, tags, eflags, &eo); } if (status == REG_OK) /* A match was found, so fill the submatch registers. */ tre_fill_pmatch(nmatch, pmatch, tnfa->cflags, tnfa, tags, eo); #ifndef TRE_USE_ALLOCA if (tags) xfree(tags); #endif /* !TRE_USE_ALLOCA */ return status; } int tre_regnexec(const regex_t *preg, const char *str, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; tre_str_type_t type = (TRE_MB_CUR_MAX == 1) ? STR_BYTE : STR_MBS; if (eflags & REG_STARTEND) { size_t slen = (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so); size_t offset = pmatch[0].rm_so; str = &str[offset]; int ret = tre_match(tnfa, str, slen, type, nmatch, pmatch, eflags, preg->shortcut); if (!(eflags & REG_NOSUB)) { for (unsigned i = 0; i < nmatch; i++) { pmatch[i].rm_so += offset; pmatch[i].rm_eo += offset; } } return ret; } else { return tre_match(tnfa, str, len, type, nmatch, pmatch, eflags, preg->shortcut); } } int tre_regexec(const regex_t *preg, const char *str, size_t nmatch, regmatch_t pmatch[], int eflags) { return tre_regnexec(preg, str, (unsigned)-1, nmatch, pmatch, eflags); } #ifdef TRE_WCHAR int tre_regwnexec(const regex_t *preg, const wchar_t *str, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; if (eflags & REG_STARTEND) { size_t slen = (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so); size_t offset = pmatch[0].rm_so; str = &str[offset]; int ret = tre_match(tnfa, str, slen, STR_WIDE, nmatch, pmatch, eflags, preg->shortcut); if (!(eflags & REG_NOSUB)) { for (unsigned i = 0; i < nmatch; i++) { pmatch[i].rm_so += offset; pmatch[i].rm_eo += offset; } } return ret; } else { return tre_match(tnfa, str, len, STR_WIDE, nmatch, pmatch, eflags, preg->shortcut); } } int tre_regwexec(const regex_t *preg, const wchar_t *str, size_t nmatch, regmatch_t pmatch[], int eflags) { return tre_regwnexec(preg, str, (unsigned)-1, nmatch, pmatch, eflags); } #endif /* TRE_WCHAR */ int tre_reguexec(const regex_t *preg, const tre_str_source *str, size_t nmatch, regmatch_t pmatch[], int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; return tre_match(tnfa, str, (unsigned)-1, STR_USER, nmatch, pmatch, eflags, preg->shortcut); } #ifdef TRE_APPROX /* Wrapper functions for approximate regexp matching. */ static int tre_match_approx(const tre_tnfa_t *tnfa, const void *string, size_t len, tre_str_type_t type, regamatch_t *match, regaparams_t params, int eflags) { reg_errcode_t status; int *tags = NULL, eo; /* If the regexp does not use approximate matching features, the maximum cost is zero, and the approximate matcher isn't forced, use the exact matcher instead. */ if (params.max_cost == 0 && !tnfa->have_approx && !(eflags & REG_APPROX_MATCHER)) return tre_match(tnfa, string, len, type, match->nmatch, match->pmatch, eflags, NULL); /* Back references are not supported by the approximate matcher. */ if (tnfa->have_backrefs) return REG_BADPAT; if (tnfa->num_tags > 0 && match->nmatch > 0) { #if TRE_USE_ALLOCA tags = alloca(sizeof(*tags) * tnfa->num_tags); #else /* !TRE_USE_ALLOCA */ tags = xmalloc(sizeof(*tags) * tnfa->num_tags); #endif /* !TRE_USE_ALLOCA */ if (tags == NULL) return REG_ESPACE; } status = tre_tnfa_run_approx(tnfa, string, (int)len, type, tags, match, params, eflags, &eo); if (status == REG_OK) tre_fill_pmatch(match->nmatch, match->pmatch, tnfa->cflags, tnfa, tags, eo); #ifndef TRE_USE_ALLOCA if (tags) xfree(tags); #endif /* !TRE_USE_ALLOCA */ return status; } int tre_reganexec(const regex_t *preg, const char *str, size_t len, regamatch_t *match, regaparams_t params, int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; tre_str_type_t type = (TRE_MB_CUR_MAX == 1) ? STR_BYTE : STR_MBS; return tre_match_approx(tnfa, str, len, type, match, params, eflags); } int tre_regaexec(const regex_t *preg, const char *str, regamatch_t *match, regaparams_t params, int eflags) { return tre_reganexec(preg, str, (unsigned)-1, match, params, eflags); } #ifdef TRE_WCHAR int tre_regawnexec(const regex_t *preg, const wchar_t *str, size_t len, regamatch_t *match, regaparams_t params, int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; return tre_match_approx(tnfa, str, len, STR_WIDE, match, params, eflags); } int tre_regawexec(const regex_t *preg, const wchar_t *str, regamatch_t *match, regaparams_t params, int eflags) { return tre_regawnexec(preg, str, (unsigned)-1, match, params, eflags); } #endif /* TRE_WCHAR */ void tre_regaparams_default(regaparams_t *params) { memset(params, 0, sizeof(*params)); params->cost_ins = 1; params->cost_del = 1; params->cost_subst = 1; params->max_cost = INT_MAX; params->max_ins = INT_MAX; params->max_del = INT_MAX; params->max_subst = INT_MAX; params->max_err = INT_MAX; } #endif /* TRE_APPROX */ /* EOF */