aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Haberkorn <rhaberkorn@fmsbw.de>2026-06-26 23:14:44 +0200
committerRobin Haberkorn <rhaberkorn@fmsbw.de>2026-06-26 23:14:44 +0200
commiteb1fcdf5d1058f4fbdf3a2661573dd7e4d3976f3 (patch)
treecdb7caf92fd29cb3d2ab3d28f2cd5c9604c0d1c4
parent16cf84d794bfe9fdb245d38760256286384d8380 (diff)
downloadterex-eb1fcdf5d1058f4fbdf3a2661573dd7e4d3976f3.tar.gz
allow raw (ASCII) matching via REG_RAW flag, so we no longer need a compile-time flag
You no longer need to build two libraries just for supporting raw/ASCII and UTF-8 patterns. This makes using the library a lot easier and reduces the total binary size. Since strings are always `unsigned char *` now internally and the raw vs. UTF-8 decision is important only in a few select places, it would make no sense to use meta-programming techniques. The test suite has been extended and is now fixed for cases with embedded non-printable characters.
-rw-r--r--Makefile.am4
-rw-r--r--Makefile.linux (renamed from Makefile)10
-rw-r--r--regalone.h24
-rw-r--r--regc_lex.c28
-rw-r--r--regc_locale.c55
-rw-r--r--regcomp.c25
-rw-r--r--regcustom.h16
-rw-r--r--rege_dfa.c34
-rw-r--r--regex.h10
-rw-r--r--regexec.c36
-rwxr-xr-xregtest_terex.sh108
11 files changed, 193 insertions, 157 deletions
diff --git a/Makefile.am b/Makefile.am
index 3de47d8..503206a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,7 +5,3 @@ libterex_la_SOURCES = regcomp.c regexec.c regerror.c regfree.c \
regalone.h regcustom.h regerrs.h regex.h regguts.h
# included from regcomp.c and regexec.c
EXTRA_libterex_la_SOURCES = regc_color.c regc_cvec.c regc_lex.c regc_locale.c regc_nfa.c
-
-noinst_LTLIBRARIES += libteurex.la
-libteurex_la_CFLAGS = -DREGEX_UTF8
-libteurex_la_SOURCES = $(libterex_la_SOURCES)
diff --git a/Makefile b/Makefile.linux
index c7437fe..e1dac8f 100644
--- a/Makefile
+++ b/Makefile.linux
@@ -6,12 +6,12 @@ CFLAGS = -Wall -DREGEX_STANDALONE -fPIC -DREG_DEBUG -g
LDFLAGS = -shared
SRCS = regcomp.c regexec.c regerror.c regfree.c
OBJS = $(SRCS:.c=.o)
-BINS = libterex.so libteurex.so
-all:
- make libterex.so
- rm -f $(OBJS)
- make "CFLAGS=$(CFLAGS) -DREGEX_UTF8" libteurex.so
+BINS = libterex.so
+
+all: libterex.so
+
$(BINS): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS)
+
clean:
rm -f $(OBJS) $(BINS)
diff --git a/regalone.h b/regalone.h
index e05fdb8..110e787 100644
--- a/regalone.h
+++ b/regalone.h
@@ -35,23 +35,13 @@ typedef unsigned char chr;
#define Tcl_UniCharToUtfDString(s,l,ds) ((char *)(s))
#define Tcl_DStringFree(ds) do (void)(ds); while (0)
-#ifdef REGEX_UTF8
-# define Tcl_UniCharToLower(c) towlower(c)
-# define Tcl_UniCharToUpper(c) towupper(c)
-# define Tcl_UniCharToTitle(c) towupper(c)
-# define Tcl_UniCharIsAlpha(c) iswalpha(c)
-# define Tcl_UniCharIsAlnum(c) iswalnum(c)
-# define Tcl_UniCharIsDigit(c) iswdigit(c)
-# define Tcl_UniCharIsSpace(c) iswspace(c)
-#else
-# define Tcl_UniCharToLower(c) tolower(c)
-# define Tcl_UniCharToUpper(c) toupper(c)
-# define Tcl_UniCharToTitle(c) toupper(c)
-# define Tcl_UniCharIsAlpha(c) isalpha(c)
-# define Tcl_UniCharIsAlnum(c) isalnum(c)
-# define Tcl_UniCharIsDigit(c) isdigit(c)
-# define Tcl_UniCharIsSpace(c) isspace(c)
-#endif
+#define Tcl_UniCharToLower(c) towlower(c)
+#define Tcl_UniCharToUpper(c) towupper(c)
+#define Tcl_UniCharToTitle(c) towupper(c)
+#define Tcl_UniCharIsAlpha(c) iswalpha(c)
+#define Tcl_UniCharIsAlnum(c) iswalnum(c)
+#define Tcl_UniCharIsDigit(c) iswdigit(c)
+#define Tcl_UniCharIsSpace(c) iswspace(c)
/*
diff --git a/regc_lex.c b/regc_lex.c
index 2033913..f7b4c95 100644
--- a/regc_lex.c
+++ b/regc_lex.c
@@ -47,15 +47,15 @@
#define LASTTYPE(t) (v->lasttype == (t))
/* return and skip the next (unicode) character */
-#ifdef REGEX_UTF8
-#define SKIPCHR(x) do { \
- wchar_t __c; \
- v->now += mbtowc(&__c, (const char *)v->now, v->stop - v->now); \
- x = __c; \
-} while (0)
-#else
-#define SKIPCHR(x) do x = *v->now++; while (0)
-#endif
+static inline pchr
+skipchr(struct vars *v)
+{
+ if (v->cflags & REG_RAW)
+ return *v->now++;
+ wchar_t c;
+ v->now += mbtowc(&c, (const char *)v->now, v->stop - v->now);
+ return c;
+}
/* lexical contexts */
#define L_ERE 1 /* mainline ERE/ARE */
@@ -383,7 +383,7 @@ next(
* Okay, time to actually get a character.
*/
- SKIPCHR(c);
+ c = skipchr(v);
/*
* Deal with the easy contexts, punt EREs to code below.
@@ -709,7 +709,7 @@ next(
assert(!ATEOS());
if (!(v->cflags&REG_ADVF)) {/* only AREs have non-trivial escapes */
- SKIPCHR(c);
+ c = skipchr(v);
if (iscalnum(c)) {
NOTE(REG_UBSALNUM);
NOTE(REG_UUNSPEC);
@@ -766,7 +766,7 @@ lexescape(
assert(v->cflags&REG_ADVF);
assert(!ATEOS());
- SKIPCHR(c);
+ c = skipchr(v);
if (!iscalnum(c)) {
RETV(PLAIN, c);
}
@@ -790,7 +790,7 @@ lexescape(
if (ATEOS()) {
FAILW(REG_EESCAPE);
}
- SKIPCHR(c);
+ c = skipchr(v);
RETV(PLAIN, c & 037);
break;
case CHR('d'):
@@ -1055,7 +1055,7 @@ brenext(
FAILW(REG_EESCAPE);
}
- SKIPCHR(c);
+ c = skipchr(v);
switch (c) {
case CHR('{'):
INTOCON(L_BBND);
diff --git a/regc_locale.c b/regc_locale.c
index 97aa702..e55d5d7 100644
--- a/regc_locale.c
+++ b/regc_locale.c
@@ -120,16 +120,12 @@ static const struct cname {
* Unicode character-class tables.
*/
-// FIXME: Perhaps define a new type here, similar to the
-// original chr, so we don't waste space on the tables
-// in ASCII (non-UTF-8) builds.
-// Or perhaps pchr should just be like chr in the original implementation.
typedef struct crange {
pchr start;
pchr end;
} crange;
-#if defined(REGEX_STANDALONE) && ! defined(REGEX_UTF8)
+#if defined(REGEX_STANDALONE) && 0 //! defined(REGEX_UTF8)
static const crange alphaRangeTable[] = {
{0x41, 0x5a}, {0x61, 0x7a}
@@ -221,6 +217,9 @@ static const pchr printCharTable[] = {
* Declarations of Unicode character ranges. This code
* is automatically generated by the tools/uniClass.tcl script
* and used in generic/regc_locale.c. Do not modify by hand.
+ *
+ * Since this is a superset of ASCII, the same tables are used
+ * when matching with REG_RAW.
*/
/* Unicode: alphabetic characters */
@@ -724,17 +723,18 @@ element(
assert(startp < endp);
len = endp - startp;
-#ifdef REGEX_UTF8
- wchar_t c;
- if (mbtowc(&c, (const char *)startp, len) == len) {
- // single character
- return c;
- }
-#else
- if (len == 1) {
- return *startp;
+
+ if (v->cflags & REG_RAW) {
+ if (len == 1) {
+ return *startp;
+ }
+ } else {
+ wchar_t c;
+ if (mbtowc(&c, (const char *)startp, len) == len) {
+ // single character
+ return c;
+ }
}
-#endif
NOTE(REG_ULOCALE);
@@ -1146,7 +1146,7 @@ cmp(
}
/*
- - casecmp - case-independent chr-substring compare
+ - casecmp - case-independent Unicode-aware chr-substring compare
* REG_ICASE backrefs need this. It should preferably be efficient.
* Note that it does not need to report anything except equal/unequal.
* Note also that the length is exact, and the comparison should not
@@ -1158,9 +1158,28 @@ casecmp(
const chr *x, const chr *y, /* strings to compare */
size_t len) /* exact length of comparison */
{
+ const chr *xp = x, *yp = y;
+ while (xp - x < len && yp - y < len) {
+ wchar_t xc, yc;
+ xp += mbtowc(&xc, (const char *)xp, len - (xp - x));
+ yp += mbtowc(&yc, (const char *)yp, len - (yp - y));
+ if (xc != yc && towlower(xc) != towlower(yc)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ - casecmp_raw - case-independent byte-wise chr-substring compare
+ */
+static int /* 0 for equal, nonzero for unequal */
+casecmp_raw(
+ const chr *x, const chr *y, /* strings to compare */
+ size_t len) /* exact length of comparison */
+{
for (; len > 0; len--, x++, y++) {
- // FIXME: Will fail if REGEX_UTF8.
- if ((*x!=*y) && (Tcl_UniCharToLower(*x) != Tcl_UniCharToLower(*y))) {
+ if ((*x!=*y) && (tolower(*x) != tolower(*y))) {
return 1;
}
}
diff --git a/regcomp.c b/regcomp.c
index 25b1a85..f082a8b 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -181,6 +181,7 @@ static struct cvec *cclass(struct vars *, const chr *, const chr *, int);
static struct cvec *allcases(struct vars *, pchr);
static int cmp(const chr *, const chr *, size_t);
static int casecmp(const chr *, const chr *, size_t);
+static int casecmp_raw(const chr *, const chr *, size_t);
/* automatically gathered by fwd; do not hand-edit */
/* =====^!^===== end forwards =====^!^===== */
@@ -231,11 +232,15 @@ struct vars {
#define NOTE(b) (v->re->re_info |= (b)) /* note visible condition */
#define EMPTYARC(x, y) newarc(v->nfa, EMPTY, 0, x, y)
-#ifdef REGEX_UTF8
-#define DECODECHR(buf, c) wctomb((char *)buf, c)
-#else
-#define DECODECHR(buf, c) ((buf)[0] = (c), 1)
-#endif
+static inline size_t
+decodechr(struct vars *v, chr *buf, pchr c)
+{
+ if (v->cflags & REG_RAW) {
+ buf[0] = c;
+ return 1;
+ }
+ return wctomb((char *)buf, c);
+}
/* token type codes, some also used as NFA arc types */
#define EMPTY 'n' /* no token present */
@@ -445,7 +450,11 @@ compile(
g->tree = v->tree;
v->tree = NULL;
g->ntree = v->ntree;
- g->compare = (v->cflags&REG_ICASE) ? casecmp : cmp;
+ if (!(v->cflags & REG_ICASE)) {
+ g->compare = cmp;
+ } else {
+ g->compare = (v->cflags & REG_RAW) ? casecmp_raw : casecmp;
+ }
g->lacons = v->lacons;
v->lacons = NULL;
g->nlacons = v->nlacons;
@@ -1491,7 +1500,7 @@ brackpart(
onechr(v, c, lp, rp);
return;
}
- buf_len = DECODECHR(buf, c);
+ buf_len = decodechr(v, buf, c);
startc = element(v, buf, buf+buf_len);
NOERR();
break;
@@ -1536,7 +1545,7 @@ brackpart(
switch (v->nexttype) {
case PLAIN:
case RANGE:
- buf_len = DECODECHR(buf, v->nextvalue);
+ buf_len = decodechr(v, buf, v->nextvalue);
NEXT();
endc = element(v, buf, buf+buf_len);
NOERR();
diff --git a/regcustom.h b/regcustom.h
index 1b25fed..24bd130 100644
--- a/regcustom.h
+++ b/regcustom.h
@@ -109,10 +109,6 @@ typedef int32_t celt; /* Type to hold chr, or NOCELT */
#define CHRBITS 32 /* Bits in a chr; must not use sizeof */
#define CHR_MIN 0x00000000 /* Smallest and largest chr; the value */
#define CHR_MAX 0xffffffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */
-#elif defined(REGEX_STANDALONE) && ! defined(REGEX_UTF8)
-# define CHRBITS 8
-# define CHR_MIN 0x00
-# define CHR_MAX 0xff
#else
#define CHRBITS 16 /* Bits in a chr; must not use sizeof */
#define CHR_MIN 0x0000 /* Smallest and largest chr; the value */
@@ -133,15 +129,9 @@ typedef int32_t celt; /* Type to hold chr, or NOCELT */
*/
#ifdef REGEX_STANDALONE
-# ifdef REGEX_UTF8
-# define compile re_ucomp
-# define exec re_uexec
-# define __REG_NOCHAR
-# else
-# define compile re_comp
-# define exec re_exec
-# undef __REG_NOCHAR
-# endif
+#define compile re_comp
+#define exec re_exec
+#undef __REG_NOCHAR
#else
#define compile TclReComp
#define exec TclReExec
diff --git a/rege_dfa.c b/rege_dfa.c
index 32daab9..9764c33 100644
--- a/rege_dfa.c
+++ b/rege_dfa.c
@@ -70,7 +70,7 @@ longest(
co = d->cnfa->bos[(v->eflags&REG_NOTBOL) ? 0 : 1];
FDEBUG(("color %ld\n", (long)co));
} else {
- pchr c = getchr(prevchr(cp), stop);
+ pchr c = getchr(v, prevchr(v, cp), stop);
co = GETCOLOR(cm, c);
FDEBUG(("char %c (%u), color %ld\n", (char)c, c, (long)co));
}
@@ -87,32 +87,32 @@ longest(
if (v->eflags&REG_FTRACE) {
while (cp < realstop) {
FDEBUG(("+++ at c%ld +++\n", css - d->ssets));
- pchr c = getchr(cp, stop);
+ pchr c = getchr(v, cp, stop);
co = GETCOLOR(cm, c);
FDEBUG(("char %c (%u), color %ld\n", (char)c, c, (long)co));
ss = css->outs[co];
if (ss == NULL) {
- ss = miss(v, d, css, co, nextchr(cp), start);
+ ss = miss(v, d, css, co, nextchr(v, cp), start);
if (ss == NULL) {
break; /* NOTE BREAK OUT */
}
}
- cp = nextchr(cp);
+ cp = nextchr(v, cp);
ss->lastseen = cp;
css = ss;
}
} else {
while (cp < realstop) {
- pchr c = getchr(cp, stop);
+ pchr c = getchr(v, cp, stop);
co = GETCOLOR(cm, c);
ss = css->outs[co];
if (ss == NULL) {
- ss = miss(v, d, css, co, nextchr(cp), start);
+ ss = miss(v, d, css, co, nextchr(v, cp), start);
if (ss == NULL) {
break; /* NOTE BREAK OUT */
}
}
- cp = nextchr(cp);
+ cp = nextchr(v, cp);
ss->lastseen = cp;
css = ss;
}
@@ -154,7 +154,7 @@ longest(
}
}
if (post != NULL) { /* found one */
- return prevchr(post);
+ return prevchr(v, post);
}
return NULL;
@@ -202,7 +202,7 @@ shortest(
co = d->cnfa->bos[(v->eflags&REG_NOTBOL) ? 0 : 1];
FDEBUG(("color %ld\n", (long)co));
} else {
- pchr c = getchr(prevchr(cp), max);
+ pchr c = getchr(v, prevchr(v, cp), max);
co = GETCOLOR(cm, c);
FDEBUG(("char %c (%u), color %ld\n", (char)c, c, (long)co));
}
@@ -220,17 +220,17 @@ shortest(
if (v->eflags&REG_FTRACE) {
while (cp < realmax) {
FDEBUG(("--- at c%ld ---\n", css - d->ssets));
- pchr c = getchr(cp, max);
+ pchr c = getchr(v, cp, max);
co = GETCOLOR(cm, c);
FDEBUG(("char %c (%u), color %ld\n", (char)c, c, (long)co));
ss = css->outs[co];
if (ss == NULL) {
- ss = miss(v, d, css, co, nextchr(cp), start);
+ ss = miss(v, d, css, co, nextchr(v, cp), start);
if (ss == NULL) {
break; /* NOTE BREAK OUT */
}
}
- cp = nextchr(cp);
+ cp = nextchr(v, cp);
ss->lastseen = cp;
css = ss;
if ((ss->flags&POSTSTATE) && cp >= realmin) {
@@ -239,16 +239,16 @@ shortest(
}
} else {
while (cp < realmax) {
- pchr c = getchr(cp, max);
+ pchr c = getchr(v, cp, max);
co = GETCOLOR(cm, c);
ss = css->outs[co];
if (ss == NULL) {
- ss = miss(v, d, css, co, nextchr(cp), start);
+ ss = miss(v, d, css, co, nextchr(v, cp), start);
if (ss == NULL) {
break; /* NOTE BREAK OUT */
}
}
- cp = nextchr(cp);
+ cp = nextchr(v, cp);
ss->lastseen = cp;
css = ss;
if ((ss->flags&POSTSTATE) && cp >= realmin) {
@@ -267,7 +267,7 @@ shortest(
if ((ss->flags&POSTSTATE) && cp > min) {
assert(cp >= realmin);
- cp = prevchr(cp);
+ cp = prevchr(v, cp);
} else if (cp == v->stop && max == v->stop) {
co = d->cnfa->eos[(v->eflags&REG_NOTEOL) ? 0 : 1];
FDEBUG(("color %ld\n", (long)co));
@@ -781,7 +781,7 @@ pickss(
* Look for oldest, or old enough anyway.
*/
- // FIXME: is this safe if REGEX_UTF8?
+ // FIXME: is this safe if matching UTF8?
if (cp - start > d->nssets*2/3) { /* oldest 33% are expendable */
ancient = cp - d->nssets*2/3;
} else {
diff --git a/regex.h b/regex.h
index 1e32b18..c15d005 100644
--- a/regex.h
+++ b/regex.h
@@ -119,16 +119,9 @@ extern "C" {
# undef regerror
# define regfree re_free
# define regerror re_error
-// FIXME
# undef __REG_WIDE_T
# define __REG_WIDE_T unsigned char
-# undef __REG_WIDE_COMPILE
-# define __REG_WIDE_COMPILE re_ucomp
-# undef __REG_WIDE_EXEC
-# define __REG_WIDE_EXEC re_uexec
-# ifndef REGEX_UTF8
-# undef __REG_NOCHAR
-# endif
+# undef __REG_NOCHAR
#endif
/*
@@ -237,6 +230,7 @@ typedef struct {
#define REG_DUMP 004000 /* none of your business :-) */
#define REG_FAKE 010000 /* none of your business :-) */
#define REG_PROGRESS 020000 /* none of your business :-) */
+#define REG_RAW 040000 /* pattern and subject are raw ASCII (also an execution flag) */
/*
* execution
diff --git a/regexec.c b/regexec.c
index 2f8a234..e8131e2 100644
--- a/regexec.c
+++ b/regexec.c
@@ -155,11 +155,13 @@ static struct sset *pickss(struct vars *, struct dfa *, chr *, chr *);
/* automatically gathered by fwd; do not hand-edit */
/* =====^!^===== end forwards =====^!^===== */
-#ifdef REGEX_UTF8
-
static inline chr *
-nextchr(chr *s)
+nextchr(struct vars *v, chr *s)
{
+ if (v->eflags & REG_RAW) {
+ return s+1;
+ }
+
unsigned char c = (unsigned char)*s;
if (c < 0x80) /* 0xxxxxxx */
@@ -176,8 +178,12 @@ nextchr(chr *s)
}
static inline chr *
-prevchr(chr *s)
+prevchr(struct vars *v, chr *s)
{
+ if (v->eflags & REG_RAW) {
+ return s-1;
+ }
+
do {
--s;
} while (((unsigned char)*s & 0xC0) == 0x80);
@@ -186,21 +192,17 @@ prevchr(chr *s)
}
static inline pchr
-getchr(const chr *s, const chr *end)
+getchr(struct vars *v, const chr *s, const chr *end)
{
+ if (v->eflags & REG_RAW) {
+ return *s;
+ }
+
wchar_t c = 0;
mbtowc(&c, (const char *)s, end - s);
return c;
}
-#else /* !REGEX_UTF8 */
-
-static inline chr *nextchr(chr *s) { return s+1; }
-static inline chr *prevchr(chr *s) { return s-1; }
-static inline pchr getchr(const chr *s, const chr *end) { return *s; }
-
-#endif
-
/*
- exec - match regular expression
^ int exec(regex_t *, const chr *, size_t, rm_detail_t *,
@@ -399,7 +401,7 @@ find(
d = newdfa(v, cnfa, cm, &v->dfa1);
assert(!(ISERR() && d != NULL));
NOERR();
- for (begin = open; begin <= close; begin = nextchr(begin)) {
+ for (begin = open; begin <= close; begin = nextchr(v, begin)) {
MDEBUG(("\nfind trying at %ld\n", LOFF(begin)));
if (shorter) {
end = shortest(v, d, begin, begin, v->stop, NULL, &hitend);
@@ -524,7 +526,7 @@ cfindloop(
open = cold;
cold = NULL;
MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close)));
- for (begin = open; begin <= close; begin = nextchr(begin)) {
+ for (begin = open; begin <= close; begin = nextchr(v, begin)) {
MDEBUG(("\ncfind trying at %ld\n", LOFF(begin)));
estart = begin;
estop = v->stop;
@@ -571,9 +573,9 @@ cfindloop(
*/
if (shorter) {
- estart = nextchr(end);
+ estart = nextchr(v, end);
} else {
- estop = prevchr(end);
+ estop = prevchr(v, end);
}
}
}
diff --git a/regtest_terex.sh b/regtest_terex.sh
index ca499d8..29a88c5 100755
--- a/regtest_terex.sh
+++ b/regtest_terex.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/local/bin/bash
#
# Copyright (c) 2002, Stooges & Cueless CO., All rights reserved.
#
@@ -74,10 +74,6 @@ cat<<-EOF>$rgsrc
#include <string.h>
#include "regalone.h"
#include "regex.h"
- #ifdef REGEX_UTF8
- # define re_comp re_ucomp
- # define re_exec re_uexec
- #endif
size_t hexescapes2bin(unsigned char *t, char *src, size_t mxlen)
{
char *s, *xs;
@@ -108,10 +104,11 @@ cat<<-EOF>$rgsrc
char buf[1024*2];
//memset(&cre, '\0', sizeof(cre));
- nmatch = atoi(argv[1]);
- relen = hexescapes2bin(re, argv[2], sizeof(re)/sizeof(char));
- datlen = hexescapes2bin(dat, argv[3], sizeof(dat)/sizeof(char));
+ nmatch = atoi(argv[2]);
+ relen = hexescapes2bin(re, argv[3], sizeof(re)/sizeof(char));
+ datlen = hexescapes2bin(dat, argv[4], sizeof(dat)/sizeof(char));
cflags = REG_ADVANCED | (nmatch ? 0 : REG_NOSUB);
+ if ( atoi(argv[1]) != 0 ) cflags |= REG_RAW;
rc = re_comp(&cre, re, relen, cflags);
if ( rc != REG_OKAY )
{
@@ -127,7 +124,7 @@ cat<<-EOF>$rgsrc
nmatch, cre.re_nsub);
return 1;
}
- rc = re_exec(&cre, dat, datlen, NULL, 100, pmatch, 0);
+ rc = re_exec(&cre, dat, datlen, NULL, 100, pmatch, cflags & REG_RAW);
if ( rc != REG_OKAY )
{
regerror(rc, &cre, buf, sizeof(buf));
@@ -143,7 +140,7 @@ cat<<-EOF>$rgsrc
sprintf(&buf[strlen(buf)], "%s%.*s",
i>1 ? ":" : "",
(int)(pmatch[i].rm_eo-pmatch[i].rm_so),
- argv[3]+pmatch[i].rm_so);
+ argv[4]+pmatch[i].rm_so);
printf("%s\n", buf);
}
regfree(&cre);
@@ -153,51 +150,73 @@ EOF
PATH=.:$PATH
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH
-# Either this one
-#$CC -Wall -g -O0 -I. -I$H/inc -L. -lterex -o $rgbin $rgsrc # Test ascii ch
-# Or this one
-$CC -Wall -g -O0 -I. -I$H/inc -L. -lteurex -DREGEX_UTF8 -o $rgbin $rgsrc # Test wide ch
+$CC -Wall -g -O0 -I. -I$H/inc -L. -lterex -o $rgbin $rgsrc
#-----------------------------------
-resp=`$rgbin 0 "clavo" "Pablito clavo un clavito" 2>&1`
msg="Simple match"
+resp=`$rgbin 0 0 "clavo" "Pablito clavo un clavito" 2>&1`
test -z "$resp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 0 "clavo" "Pablito clavo un clavito" 2>&1`
+test -z "$resp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
-resp=`$rgbin 0 \
+msg="yyyy-mm-dd between 1900-01-01 and 2099-12-31"
+resp=`$rgbin 0 0 \
"(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])" \
"1960-10-12" 2>&1`
-msg="yyyy-mm-dd between 1900-01-01 and 2099-12-31"
test -z "$resp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 0 \
+ "(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])" \
+ "1960-10-12" 2>&1`
+test -z "$resp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
-resp=`$rgbin 0 \
+msg="yyyy-mm-dd out of 1900-01-01 and 2099-12-31"
+resp=`$rgbin 0 0 \
"(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])" \
"El arzobispo 1960-14-12 de Constantinopla" 2>&1`
-msg="yyyy-mm-dd out of 1900-01-01 and 2099-12-31"
if echo "$resp"|grep "failed to match">/dev/null;
then f_ok "$msg"; else f_no "$msg" "$resp"; fi
+resp=`$rgbin 1 0 \
+ "(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])" \
+ "El arzobispo 1960-14-12 de Constantinopla" 2>&1`
+if echo "$resp"|grep "failed to match">/dev/null;
+then f_ok "$msg (raw)"; else f_no "$msg (raw)" "$resp"; fi
#-----------------------------------
-resp=`$rgbin 0 "^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$" "432" 2>&1`
msg="1..999"
+resp=`$rgbin 0 0 "^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$" "432" 2>&1`
test -z "$resp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 0 "^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$" "432" 2>&1`
+test -z "$resp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
-resp=`$rgbin 0 "^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$" " 4321" 2>&1`
msg="Bad 1..999"
+resp=`$rgbin 0 0 "^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$" " 4321" 2>&1`
if echo "$resp"|grep "failed to match">/dev/null;
then f_ok "$msg"; else f_no "$msg" "$resp"; fi
+resp=`$rgbin 1 0 "^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$" " 4321" 2>&1`
+if echo "$resp"|grep "failed to match">/dev/null;
+then f_ok "$msg (raw)"; else f_no "$msg (raw)" "$resp"; fi
#-----------------------------------
-resp=`$rgbin 0 "word1\W+(?:\w+\W+){1,3}?word2" \
- "word1 clavo un clavito word2" 2>&1`
msg="Quantifier: One to three words between 'word1' and 'word2'"
+resp=`$rgbin 0 0 "word1\W+(?:\w+\W+){1,3}?word2" \
+ "word1 clavo un clavito word2" 2>&1`
test -z "$resp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 0 "word1\W+(?:\w+\W+){1,3}?word2" \
+ "word1 clavo un clavito word2" 2>&1`
+test -z "$resp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
-resp=`$rgbin 0 "a?a?a?a?a?aaaaaaaaaaaaaaa" \
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 2>&1`
msg="Pathological: a?^6a^15 against aaaaaaaaaaaaaaaaaa..."
+resp=`$rgbin 0 0 "a?a?a?a?a?aaaaaaaaaaaaaaa" \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 2>&1`
test -z "$resp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 0 "a?a?a?a?a?aaaaaaaaaaaaaaa" \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 2>&1`
+test -z "$resp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
-resp=`$rgbin 0 "(a|aa)*b" \
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" 2>&1`
msg="Pathological: (a|aa)*b against aaaaaaaaaaaaaaaaaa...b"
+resp=`$rgbin 0 0 "(a|aa)*b" \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" 2>&1`
test -z "$resp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 0 "(a|aa)*b" \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" 2>&1`
+test -z "$resp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
cat<<-EOF>$datsrc
#include <stdio.h>
@@ -243,9 +262,11 @@ while test $i -lt 5; do
test $i -eq 0 && expectedresp=$num || expectedresp=$expectedresp:$num
i=`expr $i + 1`
done
-resp=`$rgbin 5 "$totre" "$totdat" 2>&1`
msg="5 group patterns taken with bracket ranges"
+resp=`$rgbin 0 5 "$totre" "$totdat" 2>&1`
test "$resp" = "$expectedresp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 5 "$totre" "$totdat" 2>&1`
+test "$resp" = "$expectedresp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
i=0
totre="[a-zA-Z]+"
@@ -258,9 +279,11 @@ while test $i -lt 10; do
test $i -eq 0 && expectedresp=$num || expectedresp=$expectedresp:$num
i=`expr $i + 1`
done
-resp=`$rgbin 10 "$totre" "$totdat" 2>&1`
msg="10 group patterns taken with bracket ranges"
+resp=`$rgbin 0 10 "$totre" "$totdat" 2>&1`
test "$resp" = "$expectedresp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 10 "$totre" "$totdat" 2>&1`
+test "$resp" = "$expectedresp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
i=0
totre="[a-zA-Z]+"
@@ -273,9 +296,11 @@ while test $i -lt 99; do
test $i -eq 0 && expectedresp=$num || expectedresp=$expectedresp:$num
i=`expr $i + 1`
done
-resp=`$rgbin 99 "$totre" "$totdat" 2>&1`
msg="99 group patterns taken with bracket ranges"
+resp=`$rgbin 0 99 "$totre" "$totdat" 2>&1`
test "$resp" = "$expectedresp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 99 "$totre" "$totdat" 2>&1`
+test "$resp" = "$expectedresp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
i=0
totre="[[:alpha:]]+"
@@ -288,24 +313,35 @@ while test $i -lt 99; do
test $i -eq 0 && expectedresp=$num || expectedresp=$expectedresp:$num
i=`expr $i + 1`
done
-resp=`$rgbin 99 "$totre" "$totdat" 2>&1`
msg="99 group patterns taken with character classes"
+resp=`$rgbin 0 99 "$totre" "$totdat" 2>&1`
test "$resp" = "$expectedresp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 99 "$totre" "$totdat" 2>&1`
+test "$resp" = "$expectedresp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
-resp=`$rgbin 0 "clavo" "Pablito\00clavo un clavito" 2>&1`
msg="Binary data"
+resp=`$rgbin 0 0 "clavo" $'Pablito\01clavo un clavito' 2>&1`
test -z "$resp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 0 "clavo" $'Pablito\01clavo un clavito' 2>&1`
+test -z "$resp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
-resp=`$rgbin 0 "cl\xFFavo" "Pablito\x00cl\xFFavo un clavito" 2>&1`
msg="Binary RE and data"
+resp=`$rgbin 0 0 $'cl\xFFavo' $'Pablito\x01cl\xFFavo un clavito' 2>&1`
test -z "$resp" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 0 $'cl\xFFavo' $'Pablito\x01cl\xFFavo un clavito' 2>&1`
+test -z "$resp" && f_ok "$msg (raw)" || f_no "$msg (raw)" "$resp"
#-----------------------------------
-resp=`$rgbin 1 "(?i)(clavo)" "Pablito ClAvO un clavito" 2>&1`
msg="One group pattern with case-insensitive matching"
+resp=`$rgbin 0 1 "(?i)(clavo)" "Pablito ClAvO un clavito" 2>&1`
test "$resp" = "ClAvO" && f_ok "$msg" || f_no "$msg" "$resp"
+resp=`$rgbin 1 1 "(?i)(clavo)" "Pablito ClAvO un clavito" 2>&1`
+test "$resp" = "ClAvO" && f_ok "$msg (raw)" || f_no "$msg" "$resp (raw)"
+#-----------------------------------
+resp=`$rgbin 1 1 $'([\x01\x5F\xFF]+)' $'ABC\x5F' 2>&1`
+msg="Raw character class"
+test "$resp" = $'\x5F' && f_ok "$msg" || f_no "$msg" "$resp"
#-----------------------------------
-# Will only work if REGEX_UTF8
-resp=`$rgbin 1 '([[:alpha:]]+)' 'абвгд' 2>&1`
+resp=`$rgbin 0 1 '([[:alpha:]]+)' 'абвгд' 2>&1`
msg="Unicode character class"
test "$resp" = "абвгд" && f_ok "$msg" || f_no "$msg" "$resp"
#-----------------------------------