X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcregex.c;h=1412f20d0dd192394c3af0927b10341abe627931;hb=89429cd0dc7e29b8284d5b6066f94719509ec885;hp=c11ea8ad726040278e3976e34efaa12e0a3655c2;hpb=96ae4adfa8757be98b0587941e26d0733e1fb22e;p=crypto.git diff --git a/lib/silcutil/silcregex.c b/lib/silcutil/silcregex.c index c11ea8ad..1412f20d 100644 --- a/lib/silcutil/silcregex.c +++ b/lib/silcutil/silcregex.c @@ -25,8 +25,8 @@ Emacs-specific code and syntax table code is almost directly borrowed from GNU regexp. - The SILC Regex API by Pekka Riikonen, under the same license as the original - code. + The SILC Regex API and modifications by Pekka Riikonen, under the same + license as the original code. */ @@ -34,7 +34,7 @@ /* Modified for use in SILC Runtime Toolkit. I think we have disabled many features we could use, for the sake of simple API, which we may want to - extend later. */ + extend later. But, we've added RE_NOTBOL and RE_NOTEOL. */ #define RE_NREGS 128 /* number of registers available */ @@ -47,6 +47,8 @@ #define RE_CONTEXT_INDEP_OPS 32 /* ^$?*+ are special in all contexts */ #define RE_ANSI_HEX 64 /* ansi sequences (\n etc) and \xhh */ #define RE_NO_GNU_EXTENSIONS 128 /* no gnu extensions */ +#define RE_NOTBOL 256 /* bol fails to match */ +#define RE_NOTEOL 512 /* eol fails to match */ /* definitions for some common regexp styles */ #define RE_SYNTAX_AWK (RE_NO_BK_PARENS|RE_NO_BK_VBAR|RE_CONTEXT_INDEP_OPS) @@ -74,22 +76,22 @@ SilcResult re_compile_pattern(char *regex, int regex_size, SilcRegex compiled); translation table, or NULL if it is not used. */ int re_match(SilcRegex compiled, char *string, int size, int pos, - regexp_registers_t regs); + regexp_registers_t regs, unsigned int flags); /* This tries to match the regexp against the string. This returns the length of the matched portion, or -1 if the pattern could not be matched and -2 if an error (such as failure stack overflow) is encountered. */ int re_match_2(SilcRegex compiled, char *string1, int size1, - char *string2, int size2, int pos, regexp_registers_t regs, - int mstop); + char *string2, int size2, int pos, regexp_registers_t regs, + int mstop, unsigned int flags); /* This tries to match the regexp to the concatenation of string1 and string2. This returns the length of the matched portion, or -1 if the pattern could not be matched and -2 if an error (such as failure stack overflow) is encountered. */ int re_search(SilcRegex compiled, char *string, int size, int startpos, - int range, regexp_registers_t regs); + int range, regexp_registers_t regs, unsigned int flags); /* This rearches for a substring matching the regexp. This returns the first index at which a match is found. range specifies at how many positions to try matching; positive values indicate searching forwards, and negative @@ -99,7 +101,7 @@ int re_search(SilcRegex compiled, char *string, int size, int startpos, int re_search_2(SilcRegex compiled, char *string1, int size1, char *string2, int size2, int startpos, int range, - regexp_registers_t regs, int mstop); + regexp_registers_t regs, int mstop, unsigned int flags); /* This is like re_search, but search from the concatenation of string1 and string2. */ @@ -973,11 +975,12 @@ SilcRegex bufp; #define INITIAL_FAILURES 128 /* initial # failure points to allocate */ #define MAX_FAILURES 4100 /* max # of failure points before failing */ -int re_match_2(bufp, string1, size1, string2, size2, pos, regs, mstop) +int re_match_2(bufp, string1, size1, string2, size2, pos, regs, mstop, flags) SilcRegex bufp; char *string1, *string2; int size1, size2, pos, mstop; regexp_registers_t regs; +unsigned int flags; { struct failure_point { char *text, *partend, *code; } *failure_stack_start, *failure_sp, *failure_stack_end, @@ -1101,15 +1104,21 @@ regexp_registers_t regs; silc_free((char *)failure_stack_start); return match_end - pos; case Cbol: - if (text == string1 || text[-1] == '\n') /* text[-1] always valid */ + if (text == string1 || text[-1] == '\n') { /* text[-1] always valid */ + if (flags & RE_NOTBOL) + goto fail; break; + } goto fail; case Ceol: if (text == string2 + size2 || (text == string1 + size1 ? (size2 == 0 || *string2 == '\n') : - *text == '\n')) + *text == '\n')) { + if (flags & RE_NOTEOL) + goto fail; break; + } goto fail; case Cset: NEXTCHAR(ch); @@ -1436,21 +1445,24 @@ regexp_registers_t regs; #undef NEXTCHAR #undef PUSH_FAILURE -int re_match(bufp, string, size, pos, regs) +int re_match(bufp, string, size, pos, regs, flags) SilcRegex bufp; char *string; int size, pos; regexp_registers_t regs; +unsigned int flags; { - return re_match_2(bufp, string, size, (char *)NULL, 0, pos, regs, size); + return re_match_2(bufp, string, size, (char *)NULL, 0, pos, regs, size, + flags); } int re_search_2(bufp, string1, size1, string2, size2, pos, range, regs, - mstop) + mstop, flags) SilcRegex bufp; char *string1, *string2; int size1, size2, pos, range, mstop; regexp_registers_t regs; +unsigned int flags; { char *fastmap, *translate, *text, *partstart, *partend; int dir, ret; @@ -1550,7 +1562,8 @@ regexp_registers_t regs; continue; } assert(pos >= 0 && pos <= size1 + size2); - ret = re_match_2(bufp, string1, size1, string2, size2, pos, regs, mstop); + ret = re_match_2(bufp, string1, size1, string2, size2, pos, regs, mstop, + flags); if (ret >= 0) return pos; if (ret == -2) @@ -1559,14 +1572,15 @@ regexp_registers_t regs; return -1; } -int re_search(bufp, string, size, startpos, range, regs) +int re_search(bufp, string, size, startpos, range, regs, flags) SilcRegex bufp; char *string; int size, startpos, range; regexp_registers_t regs; +unsigned int flags; { return re_search_2(bufp, string, size, (char *)NULL, 0, - startpos, range, regs, size); + startpos, range, regs, size, flags); } /****************************** SILC Regex API ******************************/ @@ -1601,11 +1615,12 @@ SilcBool silc_regex_compile(SilcRegex regexp, const char *regex, /* Match compiled regular expression */ SilcBool silc_regex_match(SilcRegex regexp, const char *string, - SilcUInt32 num_match, SilcRegexMatch match, - SilcRegexFlags flags) + SilcUInt32 string_len, SilcUInt32 num_match, + SilcRegexMatch match, SilcRegexFlags flags) { struct re_registers regs; - int ret, i, len = strlen(string); + unsigned int f = 0; + int ret, i; if (!regexp || !string) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); @@ -1621,9 +1636,15 @@ SilcBool silc_regex_match(SilcRegex regexp, const char *string, if (num_match > RE_NREGS) num_match = RE_NREGS; + /* Set flags */ + if (flags & SILC_REGEX_NOTBOL) + f |= RE_NOTBOL; + if (flags & SILC_REGEX_NOTEOL) + f |= RE_NOTEOL; + /* Search */ - ret = re_search(regexp, (char *)string, len, 0, len, - num_match ? ®s : NULL); + ret = re_search(regexp, (char *)string, string_len, 0, string_len, + num_match ? ®s : NULL, f); if (ret < 0) { if (ret == -2) silc_set_errno(SILC_ERR); @@ -1648,3 +1669,108 @@ void silc_regex_free(SilcRegex regexp) { silc_free(regexp->buffer); } + +/* Match string */ + +SilcBool silc_regex_va(const char *string, SilcUInt32 string_len, + const char *regex, SilcBuffer match, va_list va) +{ + SilcRegexStruct reg; + SilcRegexMatch m = NULL; + SilcBuffer buf, *rets = NULL; + int i, c = 0; + + /* Compile */ + if (!silc_regex_compile(®, regex, 0)) + return FALSE; + + /* Get match pointers */ + if (match) { + rets = silc_malloc(sizeof(*rets)); + if (!rets) + return FALSE; + rets[c++] = match; + + while ((buf = va_arg(va, SilcBuffer))) { + rets = silc_realloc(rets, (c + 1) * sizeof(*rets)); + if (!rets) + return FALSE; + rets[c++] = buf; + } + + m = silc_malloc(c * sizeof(*m)); + if (!m) { + silc_free(rets); + return FALSE; + } + } + + /* Match */ + if (!silc_regex_match(®, string, string_len, c, m, 0)) { + silc_free(m); + silc_free(rets); + return FALSE; + } + + /* Return matches */ + for (i = 0; i < c; i++) { + if (m[i].start == -1) + continue; + silc_buffer_set(rets[i], (unsigned char *)string + m[i].start, + m[i].end - m[i].start); + } + + silc_free(m); + silc_free(rets); + + return TRUE; +} + +/* Match string */ + +SilcBool silc_regex(const char *string, const char *regex, + SilcBuffer match, ...) +{ + SilcBool ret; + va_list va; + + if (!string || !regex) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + + if (match) + va_start(va, match); + + ret = silc_regex_va(string, strlen(string), regex, match, va); + + if (match) + va_end(va); + + return ret; +} + +/* Match string */ + +SilcBool silc_regex_buffer(SilcBuffer buffer, const char *regex, + SilcBuffer match, ...) +{ + SilcBool ret; + va_list va; + + if (!buffer || !regex) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + + if (match) + va_start(va, match); + + ret = silc_regex_va((const char *)silc_buffer_data(buffer), + silc_buffer_len(buffer), regex, match, va); + + if (match) + va_end(va); + + return ret; +}