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.
*/
/* 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 */
#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)
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
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. */
#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,
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);
#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;
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)
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 ******************************/
SilcRegexMatch match, SilcRegexFlags flags)
{
struct re_registers regs;
+ unsigned int f = 0;
int ret, i;
if (!regexp || !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, string_len, 0, string_len,
- num_match ? ®s : NULL);
+ num_match ? ®s : NULL, f);
if (ret < 0) {
if (ret == -2)
silc_set_errno(SILC_ERR);
string = "Hello World";
SILC_LOG_DEBUG(("Match %s", string));
- if (!silc_regex_match(®, string, num_match, match, 0))
+ if (!silc_regex_match(®, string, strlen(string), num_match, match, 0))
goto err;
for (i = 0; i < num_match; i++) {
if (match[i].start != -1) {
string = "foo";
SILC_LOG_DEBUG(("Match %s", string));
- if (!silc_regex_match(®, string, 0, NULL, 0))
+ if (!silc_regex_match(®, string, strlen(string), 0, NULL, 0))
goto err;
string = "foo20";
SILC_LOG_DEBUG(("Match %s", string));
- if (!silc_regex_match(®, string, 0, NULL, 0))
+ if (!silc_regex_match(®, string, strlen(string), 0, NULL, 0))
goto err;
string = "foo20, bar, foo100, foo";
SILC_LOG_DEBUG(("Match all substrings in %s", string));
- while (silc_regex_match(®, string, 1, match, 0)) {
+ while (silc_regex_match(®, string, strlen(string), 1, match, 0)) {
SILC_LOG_DEBUG(("Match start %d", match[0].start));
sub = silc_memdup(string + match[0].start, match[0].end - match[0].start);
SILC_LOG_DEBUG(("Match substring '%s'", sub));
string = "foo20, bar, foo100, Foo, foo0";
SILC_LOG_DEBUG(("Match all substrings at once in %s", string));
- if (!silc_regex_match(®, string, num_match, match, 0))
+ if (!silc_regex_match(®, string, strlen(string), num_match, match, 0))
goto err;
for (i = 0; i < num_match; i++) {
string = "http://silcnet.org:443/foobar/pelle.html";
SILC_LOG_DEBUG(("Parse URI"));
- if (!silc_regex_match(®, string, num_match, match, 0))
+ if (!silc_regex_match(®, string, strlen(string), num_match, match, 0))
goto err;
for (i = 0; i < num_match; i++) {
string = "http://silcnet.org/";
SILC_LOG_DEBUG(("Parse URI"));
- if (!silc_regex_match(®, string, num_match, match, 0))
+ if (!silc_regex_match(®, string, strlen(string), num_match, match, 0))
goto err;
for (i = 0; i < num_match; i++) {
string = "ab";
SILC_LOG_DEBUG(("Match all substrings at once in %s", string));
- if (!silc_regex_match(®, string, num_match, match, 0))
+ if (!silc_regex_match(®, string, strlen(string), num_match, match, 0))
goto err;
for (i = 0; i < num_match; i++) {
silc_regex_free(®);
+ regex = "^a";
+ SILC_LOG_DEBUG(("Regex %s", regex));
+ if (!silc_regex_compile(®, regex, 0))
+ goto err;
+
+ string = "a";
+ SILC_LOG_DEBUG(("Test NOTBOL flag", string));
+ if (silc_regex_match(®, string, strlen(string), 0, NULL,
+ SILC_REGEX_NOTBOL))
+ goto err;
+ if (silc_errno != SILC_ERR_NOT_FOUND)
+ goto err;
+ SILC_LOG_DEBUG(("Did not match (OK)"));
+
+ silc_regex_free(®);
+
+ regex = "a$";
+ SILC_LOG_DEBUG(("Regex %s", regex));
+ if (!silc_regex_compile(®, regex, 0))
+ goto err;
+
+ string = "a";
+ SILC_LOG_DEBUG(("Test NOTEOL flag", string));
+ if (silc_regex_match(®, string, strlen(string), 0, NULL,
+ SILC_REGEX_NOTEOL))
+ goto err;
+ if (silc_errno != SILC_ERR_NOT_FOUND)
+ goto err;
+ SILC_LOG_DEBUG(("Did not match (OK)"));
+
+ silc_regex_free(®);
+
success = TRUE;
err: