Index: user/gabor/tre-integration/contrib/tre/lib/regexec.c =================================================================== --- user/gabor/tre-integration/contrib/tre/lib/regexec.c (revision 221750) +++ user/gabor/tre-integration/contrib/tre/lib/regexec.c (revision 221751) @@ -1,348 +1,370 @@ /* 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 #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 "tre-internal.h" #include "xmalloc.h" /* 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) { reg_errcode_t status; int *tags = NULL, eo; 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; - return tre_match(tnfa, str, len, type, nmatch, pmatch, eflags); + if (eflags & REG_STARTEND) + { + off_t s_off = pmatch[0].rm_so; + off_t e_off = pmatch[0].rm_eo; + size_t slen = e_off - s_off; + char *sstr = xmalloc(slen); + strncpy(sstr, &str[s_off], slen); + int ret = tre_match(tnfa, sstr, slen, type, nmatch, pmatch, eflags); + if (!(eflags & REG_NOSUB)) + { + for (unsigned i = 0; i < nmatch; i++) + { + pmatch[i].rm_so += slen; + pmatch[i].rm_eo += slen; + } + } + return ret; + } + else + { + return tre_match(tnfa, str, len, type, nmatch, pmatch, eflags); + } } 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; return tre_match(tnfa, str, len, STR_WIDE, nmatch, pmatch, eflags); } 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); } #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); /* 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 */ Index: user/gabor/tre-integration/include/tre.h =================================================================== --- user/gabor/tre-integration/include/tre.h (revision 221750) +++ user/gabor/tre-integration/include/tre.h (revision 221751) @@ -1,227 +1,228 @@ /* tre.h - TRE public API definitions This software is released under a BSD-style license. See the file LICENSE for details and copyright. */ #ifndef TRE_H #define TRE_H 1 #include #define TRE_WCHAR 1 #define TRE_APPROX 1 #ifdef __cplusplus extern "C" { #endif typedef int regoff_t; typedef struct { size_t re_nsub; /* Number of parenthesized subexpressions. */ void *value; /* For internal use only. */ } regex_t; typedef struct { regoff_t rm_so; regoff_t rm_eo; } regmatch_t; typedef enum { REG_OK = 0, /* No error. */ /* POSIX tre_regcomp() return error codes. (In the order listed in the standard.) */ REG_NOMATCH, /* No match. */ REG_BADPAT, /* Invalid regexp. */ REG_ECOLLATE, /* Unknown collating element. */ REG_ECTYPE, /* Unknown character class name. */ REG_EESCAPE, /* Trailing backslash. */ REG_ESUBREG, /* Invalid back reference. */ REG_EBRACK, /* "[]" imbalance */ REG_EPAREN, /* "\(\)" or "()" imbalance */ REG_EBRACE, /* "\{\}" or "{}" imbalance */ REG_BADBR, /* Invalid content of {} */ REG_ERANGE, /* Invalid use of range operator */ REG_ESPACE, /* Out of memory. */ REG_BADRPT /* Invalid use of repetition operators. */ } reg_errcode_t; /* POSIX tre_regcomp() flags. */ #define REG_EXTENDED 1 #define REG_ICASE (REG_EXTENDED << 1) #define REG_NEWLINE (REG_ICASE << 1) #define REG_NOSUB (REG_NEWLINE << 1) /* Extra tre_regcomp() flags. */ #define REG_BASIC 0 #define REG_LITERAL (REG_NOSUB << 1) #define REG_RIGHT_ASSOC (REG_LITERAL << 1) #define REG_UNGREEDY (REG_RIGHT_ASSOC << 1) /* POSIX tre_regexec() flags. */ #define REG_NOTBOL 1 #define REG_NOTEOL (REG_NOTBOL << 1) +#define REG_STARTEND (REG_NOTEOL << 1) /* Extra tre_regexec() flags. */ #define REG_APPROX_MATCHER (REG_NOTEOL << 1) #define REG_BACKTRACKING_MATCHER (REG_APPROX_MATCHER << 1) /* REG_NOSPEC and REG_LITERAL mean the same thing. */ #if defined(REG_LITERAL) && !defined(REG_NOSPEC) #define REG_NOSPEC REG_LITERAL #elif defined(REG_NOSPEC) && !defined(REG_LITERAL) #define REG_LITERAL REG_NOSPEC #endif /* defined(REG_NOSPEC) */ /* The maximum number of iterations in a bound expression. */ #undef RE_DUP_MAX #define RE_DUP_MAX 255 /* The POSIX.2 regexp functions */ extern int tre_regcomp(regex_t *preg, const char *regex, int cflags); extern int tre_regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); extern size_t tre_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); extern void tre_regfree(regex_t *preg); #ifdef TRE_WCHAR #include /* Wide character versions (not in POSIX.2). */ extern int tre_regwcomp(regex_t *preg, const wchar_t *regex, int cflags); extern int tre_regwexec(const regex_t *preg, const wchar_t *string, size_t nmatch, regmatch_t pmatch[], int eflags); #endif /* TRE_WCHAR */ /* Versions with a maximum length argument and therefore the capability to handle null characters in the middle of the strings (not in POSIX.2). */ extern int tre_regncomp(regex_t *preg, const char *regex, size_t len, int cflags); extern int tre_regnexec(const regex_t *preg, const char *string, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags); #ifdef TRE_WCHAR extern int tre_regwncomp(regex_t *preg, const wchar_t *regex, size_t len, int cflags); extern int tre_regwnexec(const regex_t *preg, const wchar_t *string, size_t len, size_t nmatch, regmatch_t pmatch[], int eflags); #endif /* TRE_WCHAR */ #ifdef TRE_APPROX /* Approximate matching parameter struct. */ typedef struct { int cost_ins; /* Default cost of an inserted character. */ int cost_del; /* Default cost of a deleted character. */ int cost_subst; /* Default cost of a substituted character. */ int max_cost; /* Maximum allowed cost of a match. */ int max_ins; /* Maximum allowed number of inserts. */ int max_del; /* Maximum allowed number of deletes. */ int max_subst; /* Maximum allowed number of substitutes. */ int max_err; /* Maximum allowed number of errors total. */ } regaparams_t; /* Approximate matching result struct. */ typedef struct { size_t nmatch; /* Length of pmatch[] array. */ regmatch_t *pmatch; /* Submatch data. */ int cost; /* Cost of the match. */ int num_ins; /* Number of inserts in the match. */ int num_del; /* Number of deletes in the match. */ int num_subst; /* Number of substitutes in the match. */ } regamatch_t; /* Approximate matching functions. */ extern int tre_regaexec(const regex_t *preg, const char *string, regamatch_t *match, regaparams_t params, int eflags); extern int tre_reganexec(const regex_t *preg, const char *string, size_t len, regamatch_t *match, regaparams_t params, int eflags); #ifdef TRE_WCHAR /* Wide character approximate matching. */ extern int tre_regawexec(const regex_t *preg, const wchar_t *string, regamatch_t *match, regaparams_t params, int eflags); extern int tre_regawnexec(const regex_t *preg, const wchar_t *string, size_t len, regamatch_t *match, regaparams_t params, int eflags); #endif /* TRE_WCHAR */ /* Sets the parameters to default values. */ extern void tre_regaparams_default(regaparams_t *params); #endif /* TRE_APPROX */ #ifdef TRE_WCHAR typedef wchar_t tre_char_t; #else /* !TRE_WCHAR */ typedef unsigned char tre_char_t; #endif /* !TRE_WCHAR */ typedef struct { int (*get_next_char)(tre_char_t *c, unsigned int *pos_add, void *context); void (*rewind)(size_t pos, void *context); int (*compare)(size_t pos1, size_t pos2, size_t len, void *context); void *context; } tre_str_source; extern int tre_reguexec(const regex_t *preg, const tre_str_source *string, size_t nmatch, regmatch_t pmatch[], int eflags); /* Returns the version string. The returned string is static. */ extern char * tre_version(void); /* Returns the value for a config parameter. The type to which `result' must point to depends of the value of `query', see documentation for more details. */ extern int tre_config(int query, void *result); enum { TRE_CONFIG_APPROX, TRE_CONFIG_WCHAR, TRE_CONFIG_MULTIBYTE, TRE_CONFIG_SYSTEM_ABI, TRE_CONFIG_VERSION }; /* Returns 1 if the compiled pattern has back references, 0 if not. */ extern int tre_have_backrefs(const regex_t *preg); /* Returns 1 if the compiled pattern uses approximate matching features, 0 if not. */ extern int tre_have_approx(const regex_t *preg); #ifdef __cplusplus } #endif #endif /* TRE_H */ /* EOF */