From owner-svn-src-user@FreeBSD.ORG Wed Sep 14 18:07:19 2011 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 40D37106564A; Wed, 14 Sep 2011 18:07:19 +0000 (UTC) (envelope-from gabor@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2F6AE8FC14; Wed, 14 Sep 2011 18:07:19 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p8EI7JKa037023; Wed, 14 Sep 2011 18:07:19 GMT (envelope-from gabor@svn.freebsd.org) Received: (from gabor@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p8EI7JuE037018; Wed, 14 Sep 2011 18:07:19 GMT (envelope-from gabor@svn.freebsd.org) Message-Id: <201109141807.p8EI7JuE037018@svn.freebsd.org> From: Gabor Kovesdan Date: Wed, 14 Sep 2011 18:07:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r225558 - in user/gabor/tre-integration/tools/test/regex: . att att/tests printheur X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 14 Sep 2011 18:07:19 -0000 Author: gabor Date: Wed Sep 14 18:07:18 2011 New Revision: 225558 URL: http://svn.freebsd.org/changeset/base/225558 Log: - Add AT&T regex regression test and integrate it to our test suite. It has a BSD-like license. Added: user/gabor/tre-integration/tools/test/regex/att/ user/gabor/tre-integration/tools/test/regex/att/Makefile (contents, props changed) user/gabor/tre-integration/tools/test/regex/att/testregex.c (contents, props changed) user/gabor/tre-integration/tools/test/regex/att/tests/ user/gabor/tre-integration/tools/test/regex/att/tests/basic.dat user/gabor/tre-integration/tools/test/regex/att/tests/categorize.dat user/gabor/tre-integration/tools/test/regex/att/tests/forcedassoc.dat user/gabor/tre-integration/tools/test/regex/att/tests/leftassoc.dat user/gabor/tre-integration/tools/test/regex/att/tests/nullsubexpr.dat user/gabor/tre-integration/tools/test/regex/att/tests/repetition.dat user/gabor/tre-integration/tools/test/regex/att/tests/rightassoc.dat Modified: user/gabor/tre-integration/tools/test/regex/Makefile user/gabor/tre-integration/tools/test/regex/printheur/printheur.c Modified: user/gabor/tre-integration/tools/test/regex/Makefile ============================================================================== --- user/gabor/tre-integration/tools/test/regex/Makefile Wed Sep 14 15:47:18 2011 (r225557) +++ user/gabor/tre-integration/tools/test/regex/Makefile Wed Sep 14 18:07:18 2011 (r225558) @@ -1,13 +1,17 @@ # $FreeBSD$ -SUBDIR= regmatch +SUBDIR= att +SUBDIR+=regmatch TESTS= bre.tests TESTS+= ere.tests TESTS+= bre.hu_HU.ISO8859-2.tests TESTS+= bre.es_ES.ISO8859-1.tests -test: regmatch +test-all: test-freebsd test-att + +test-freebsd: regmatch + @echo "===== Running FreeBSD regex tests =====" .for t in ${TESTS} @echo "=== Running test ${t} ===" @flags=`grep '# *FLAGS' tests/${t} | sed 's|# *FLAGS *||g'`; \ @@ -25,4 +29,19 @@ test: regmatch done .endfor +ATT_TESTS= basic.dat +ATT_TESTS+=categorize.dat +ATT_TESTS+=nullsubexpr.dat +ATT_TESTS+=leftassoc.dat +ATT_TESTS+=rightassoc.dat +ATT_TESTS+=forcedassoc.dat +ATT_TESTS+=repetition.dat + +test-att: att + @echo "===== Running AT&T regex tests =====" +.for t in ${ATT_TESTS} + @echo "=== Running test ${t} ===" + ${.CURDIR}/att/testregex < ${.CURDIR}/att/tests/${t} +.endfor + .include Added: user/gabor/tre-integration/tools/test/regex/att/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/gabor/tre-integration/tools/test/regex/att/Makefile Wed Sep 14 18:07:18 2011 (r225558) @@ -0,0 +1,6 @@ +# $FreeBSD$ + +PROG= testregex +NO_MAN= yes + +.include Added: user/gabor/tre-integration/tools/test/regex/att/testregex.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/gabor/tre-integration/tools/test/regex/att/testregex.c Wed Sep 14 18:07:18 2011 (r225558) @@ -0,0 +1,2286 @@ +#pragma prototyped noticed + +/* + * regex(3) test harness + * + * build: cc -o testregex testregex.c + * help: testregex --man + * note: REG_* features are detected by #ifdef; if REG_* are enums + * then supply #define REG_foo REG_foo for each enum REG_foo + * + * Glenn Fowler + * AT&T Research + * + * PLEASE: publish your tests so everyone can benefit + * + * The following license covers testregex.c and all associated test data. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following disclaimer: + * + * THIS SOFTWARE IS PROVIDED BY AT&T ``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 AT&T 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. + */ + +static const char id[] = "\n@(#)$Id: testregex (AT&T Research) 2010-06-10 $\0\n"; + +#if _PACKAGE_ast +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __STDC__ +#include +#include +#endif + +#ifndef RE_DUP_MAX +#define RE_DUP_MAX 32767 +#endif + +#if !_PACKAGE_ast +#undef REG_DISCIPLINE +#endif + +#ifndef REG_DELIMITED +#undef _REG_subcomp +#endif + +#define TEST_ARE 0x00000001 +#define TEST_BRE 0x00000002 +#define TEST_ERE 0x00000004 +#define TEST_KRE 0x00000008 +#define TEST_LRE 0x00000010 +#define TEST_SRE 0x00000020 + +#define TEST_EXPAND 0x00000100 +#define TEST_LENIENT 0x00000200 + +#define TEST_QUERY 0x00000400 +#define TEST_SUB 0x00000800 +#define TEST_UNSPECIFIED 0x00001000 +#define TEST_VERIFY 0x00002000 +#define TEST_AND 0x00004000 +#define TEST_OR 0x00008000 + +#define TEST_DELIMIT 0x00010000 +#define TEST_OK 0x00020000 +#define TEST_SAME 0x00040000 + +#define TEST_ACTUAL 0x00100000 +#define TEST_BASELINE 0x00200000 +#define TEST_FAIL 0x00400000 +#define TEST_PASS 0x00800000 +#define TEST_SUMMARY 0x01000000 + +#define TEST_IGNORE_ERROR 0x02000000 +#define TEST_IGNORE_OVER 0x04000000 +#define TEST_IGNORE_POSITION 0x08000000 + +#define TEST_CATCH 0x10000000 +#define TEST_VERBOSE 0x20000000 + +#define TEST_DECOMP 0x40000000 + +#define TEST_GLOBAL (TEST_ACTUAL|TEST_AND|TEST_BASELINE|TEST_CATCH|TEST_FAIL|TEST_IGNORE_ERROR|TEST_IGNORE_OVER|TEST_IGNORE_POSITION|TEST_OR|TEST_PASS|TEST_SUMMARY|TEST_VERBOSE) + +#ifdef REG_DISCIPLINE + + +#include + +typedef struct Disc_s +{ + regdisc_t disc; + int ordinal; + Sfio_t* sp; +} Disc_t; + +static void* +compf(const regex_t* re, const char* xstr, size_t xlen, regdisc_t* disc) +{ + Disc_t* dp = (Disc_t*)disc; + + return (void*)((char*)0 + ++dp->ordinal); +} + +static int +execf(const regex_t* re, void* data, const char* xstr, size_t xlen, const char* sstr, size_t slen, char** snxt, regdisc_t* disc) +{ + Disc_t* dp = (Disc_t*)disc; + + sfprintf(dp->sp, "{%-.*s}(%lu:%d)", xlen, xstr, (char*)data - (char*)0, slen); + return atoi(xstr); +} + +static void* +resizef(void* handle, void* data, size_t size) +{ + if (!size) + return 0; + return stkalloc((Sfio_t*)handle, size); +} + +#endif + +#ifndef NiL +#ifdef __STDC__ +#define NiL 0 +#else +#define NiL (char*)0 +#endif +#endif + +#define H(x) do{if(html)fprintf(stderr,x);}while(0) +#define T(x) fprintf(stderr,x) + +static void +help(int html) +{ +H("\n"); +H("\n"); +H("\n"); +H("testregex man document\n"); +H("\n"); +H("\n"); +H("
\n");
+T("NAME\n");
+T("  testregex - regex(3) test harness\n");
+T("\n");
+T("SYNOPSIS\n");
+T("  testregex [ options ]\n");
+T("\n");
+T("DESCRIPTION\n");
+T("  testregex reads regex(3) test specifications, one per line, from the\n");
+T("  standard input and writes one output line for each failed test. A\n");
+T("  summary line is written after all tests are done. Each successful\n");
+T("  test is run again with REG_NOSUB. Unsupported features are noted\n");
+T("  before the first test, and tests requiring these features are\n");
+T("  silently ignored.\n");
+T("\n");
+T("OPTIONS\n");
+T("  -c	catch signals and non-terminating calls\n");
+T("  -e	ignore error return mismatches\n");
+T("  -h	list help on standard error\n");
+T("  -n	do not repeat successful tests with regnexec()\n");
+T("  -o	ignore match[] overrun errors\n");
+T("  -p	ignore negative position mismatches\n");
+T("  -s	use stack instead of malloc\n");
+T("  -x	do not repeat successful tests with REG_NOSUB\n");
+T("  -v	list each test line\n");
+T("  -A	list failed test lines with actual answers\n");
+T("  -B	list all test lines with actual answers\n");
+T("  -F	list failed test lines\n");
+T("  -P	list passed test lines\n");
+T("  -S	output one summary line\n");
+T("\n");
+T("INPUT FORMAT\n");
+T("  Input lines may be blank, a comment beginning with #, or a test\n");
+T("  specification. A specification is five fields separated by one\n");
+T("  or more tabs. NULL denotes the empty string and NIL denotes the\n");
+T("  0 pointer.\n");
+T("\n");
+T("  Field 1: the regex(3) flags to apply, one character per REG_feature\n");
+T("  flag. The test is skipped if REG_feature is not supported by the\n");
+T("  implementation. If the first character is not [BEASKLP] then the\n");
+T("  specification is a global control line. One or more of [BEASKLP] may be\n");
+T("  specified; the test will be repeated for each mode.\n");
+T("\n");
+T("    B 	basic			BRE	(grep, ed, sed)\n");
+T("    E 	REG_EXTENDED		ERE	(egrep)\n");
+T("    A	REG_AUGMENTED		ARE	(egrep with negation)\n");
+T("    S	REG_SHELL		SRE	(sh glob)\n");
+T("    K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)\n");
+T("    L	REG_LITERAL		LRE	(fgrep)\n");
+T("\n");
+T("    a	REG_LEFT|REG_RIGHT	implicit ^...$\n");
+T("    b	REG_NOTBOL		lhs does not match ^\n");
+T("    c	REG_COMMENT		ignore space and #...\\n\n");
+T("    d	REG_SHELL_DOT		explicit leading . match\n");
+T("    e	REG_NOTEOL		rhs does not match $\n");
+T("    f	REG_MULTIPLE		multiple \\n separated patterns\n");
+T("    g	FNM_LEADING_DIR		testfnmatch only -- match until /\n");
+T("    h	REG_MULTIREF		multiple digit backref\n");
+T("    i	REG_ICASE		ignore case\n");
+T("    j	REG_SPAN		. matches \\n\n");
+T("    k	REG_ESCAPE		\\ to ecape [...] delimiter\n");
+T("    l	REG_LEFT		implicit ^...\n");
+T("    m	REG_MINIMAL		minimal match\n");
+T("    n	REG_NEWLINE		explicit \\n match\n");
+T("    o	REG_ENCLOSED		(|&) magic inside [@|&](...)\n");
+T("    p	REG_SHELL_PATH		explicit / match\n");
+T("    q	REG_DELIMITED		delimited pattern\n");
+T("    r	REG_RIGHT		implicit ...$\n");
+T("    s	REG_SHELL_ESCAPED	\\ not special\n");
+T("    t	REG_MUSTDELIM		all delimiters must be specified\n");
+T("    u	standard unspecified behavior -- errors not counted\n");
+T("    v	REG_CLASS_ESCAPE	\\ special inside [...]\n");
+T("    w	REG_NOSUB		no subexpression match array\n");
+T("    x	REG_LENIENT		let some errors slide\n");
+T("    y	REG_LEFT		regexec() implicit ^...\n");
+T("    z	REG_NULL		NULL subexpressions ok\n");
+T("    $	                        expand C \\c escapes in fields 2 and 3\n");
+T("    /	                        field 2 is a regsubcomp() expression\n");
+T("    =	                        field 3 is a regdecomp() expression\n");
+T("\n");
+T("  Field 1 control lines:\n");
+T("\n");
+T("    C		set LC_COLLATE and LC_CTYPE to locale in field 2\n");
+T("\n");
+T("    ?test ...	output field 5 if passed and != EXPECTED, silent otherwise\n");
+T("    &test ...	output field 5 if current and previous passed\n");
+T("    |test ...	output field 5 if current passed and previous failed\n");
+T("    ; ...	output field 2 if previous failed\n");
+T("    {test ...	skip if failed until }\n");
+T("    }		end of skip\n");
+T("\n");
+T("    : comment		comment copied as output NOTE\n");
+T("    :comment:test	:comment: ignored\n");
+T("    N[OTE] comment	comment copied as output NOTE\n");
+T("    T[EST] comment	comment\n");
+T("\n");
+T("    number		use number for nmatch (20 by default)\n");
+T("\n");
+T("  Field 2: the regular expression pattern; SAME uses the pattern from\n");
+T("    the previous specification. RE_DUP_MAX inside {...} expands to the\n");
+T("    value from .\n");
+T("\n");
+T("  Field 3: the string to match. X...{RE_DUP_MAX} expands to RE_DUP_MAX\n");
+T("    copies of X.\n");
+T("\n");
+T("  Field 4: the test outcome. This is either one of the posix error\n");
+T("    codes (with REG_ omitted) or the match array, a list of (m,n)\n");
+T("    entries with m and n being first and last+1 positions in the\n");
+T("    field 3 string, or NULL if REG_NOSUB is in effect and success\n");
+T("    is expected. BADPAT is acceptable in place of any regcomp(3)\n");
+T("    error code. The match[] array is initialized to (-2,-2) before\n");
+T("    each test. All array elements from 0 to nmatch-1 must be specified\n");
+T("    in the outcome. Unspecified endpoints (offset -1) are denoted by ?.\n");
+T("    Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a\n");
+T("    matched (?{...}) expression, where x is the text enclosed by {...},\n");
+T("    o is the expression ordinal counting from 1, and n is the length of\n");
+T("    the unmatched portion of the subject string. If x starts with a\n");
+T("    number then that is the return value of re_execf(), otherwise 0 is\n");
+T("    returned. RE_DUP_MAX[-+]N expands to the  value -+N.\n");
+T("\n");
+T("  Field 5: optional comment appended to the report.\n");
+T("\n");
+T("CAVEAT\n");
+T("    If a regex implementation misbehaves with memory then all bets are off.\n");
+T("\n");
+T("CONTRIBUTORS\n");
+T("  Glenn Fowler    gsf@research.att.com        (ksh strmatch, regex extensions)\n");
+T("  David Korn      dgk@research.att.com        (ksh glob matcher)\n");
+T("  Doug McIlroy    mcilroy@dartmouth.edu       (ast regex/testre in C++)\n");
+T("  Tom Lord        lord@regexps.com            (rx tests)\n");
+T("  Henry Spencer   henry@zoo.toronto.edu       (original public regex)\n");
+T("  Andrew Hume     andrew@research.att.com     (gre tests)\n");
+T("  John Maddock    John_Maddock@compuserve.com (regex++ tests)\n");
+T("  Philip Hazel    ph10@cam.ac.uk              (pcre tests)\n");
+T("  Ville Laurikari vl@iki.fi                   (libtre tests)\n");
+H("
\n"); +H("\n"); +H("\n"); +} + +#ifndef elementsof +#define elementsof(x) (sizeof(x)/sizeof(x[0])) +#endif + +#ifndef streq +#define streq(a,b) (*(a)==*(b)&&!strcmp(a,b)) +#endif + +#define HUNG 2 +#define NOTEST (~0) + +#ifndef REG_TEST_DEFAULT +#define REG_TEST_DEFAULT 0 +#endif + +#ifndef REG_EXEC_DEFAULT +#define REG_EXEC_DEFAULT 0 +#endif + +static const char* unsupported[] = +{ + "BASIC", +#ifndef REG_EXTENDED + "EXTENDED", +#endif +#ifndef REG_AUGMENTED + "AUGMENTED", +#endif +#ifndef REG_SHELL + "SHELL", +#endif + +#ifndef REG_CLASS_ESCAPE + "CLASS_ESCAPE", +#endif +#ifndef REG_COMMENT + "COMMENT", +#endif +#ifndef REG_DELIMITED + "DELIMITED", +#endif +#ifndef REG_DISCIPLINE + "DISCIPLINE", +#endif +#ifndef REG_ESCAPE + "ESCAPE", +#endif +#ifndef REG_ICASE + "ICASE", +#endif +#ifndef REG_LEFT + "LEFT", +#endif +#ifndef REG_LENIENT + "LENIENT", +#endif +#ifndef REG_LITERAL + "LITERAL", +#endif +#ifndef REG_MINIMAL + "MINIMAL", +#endif +#ifndef REG_MULTIPLE + "MULTIPLE", +#endif +#ifndef REG_MULTIREF + "MULTIREF", +#endif +#ifndef REG_MUSTDELIM + "MUSTDELIM", +#endif +#ifndef REG_NEWLINE + "NEWLINE", +#endif +#ifndef REG_NOTBOL + "NOTBOL", +#endif +#ifndef REG_NOTEOL + "NOTEOL", +#endif +#ifndef REG_NULL + "NULL", +#endif +#ifndef REG_RIGHT + "RIGHT", +#endif +#ifndef REG_SHELL_DOT + "SHELL_DOT", +#endif +#ifndef REG_SHELL_ESCAPED + "SHELL_ESCAPED", +#endif +#ifndef REG_SHELL_GROUP + "SHELL_GROUP", +#endif +#ifndef REG_SHELL_PATH + "SHELL_PATH", +#endif +#ifndef REG_SPAN + "SPAN", +#endif +#if REG_NOSUB & REG_TEST_DEFAULT + "SUBMATCH", +#endif +#if !_REG_nexec + "regnexec", +#endif +#if !_REG_subcomp + "regsubcomp", +#endif +#if !_REG_decomp + "redecomp", +#endif + 0 +}; + +#ifndef REG_CLASS_ESCAPE +#define REG_CLASS_ESCAPE NOTEST +#endif +#ifndef REG_COMMENT +#define REG_COMMENT NOTEST +#endif +#ifndef REG_DELIMITED +#define REG_DELIMITED NOTEST +#endif +#ifndef REG_ESCAPE +#define REG_ESCAPE NOTEST +#endif +#ifndef REG_ICASE +#define REG_ICASE NOTEST +#endif +#ifndef REG_LEFT +#define REG_LEFT NOTEST +#endif +#ifndef REG_LENIENT +#define REG_LENIENT 0 +#endif +#ifndef REG_MINIMAL +#define REG_MINIMAL NOTEST +#endif +#ifndef REG_MULTIPLE +#define REG_MULTIPLE NOTEST +#endif +#ifndef REG_MULTIREF +#define REG_MULTIREF NOTEST +#endif +#ifndef REG_MUSTDELIM +#define REG_MUSTDELIM NOTEST +#endif +#ifndef REG_NEWLINE +#define REG_NEWLINE NOTEST +#endif +#ifndef REG_NOTBOL +#define REG_NOTBOL NOTEST +#endif +#ifndef REG_NOTEOL +#define REG_NOTEOL NOTEST +#endif +#ifndef REG_NULL +#define REG_NULL NOTEST +#endif +#ifndef REG_RIGHT +#define REG_RIGHT NOTEST +#endif +#ifndef REG_SHELL_DOT +#define REG_SHELL_DOT NOTEST +#endif +#ifndef REG_SHELL_ESCAPED +#define REG_SHELL_ESCAPED NOTEST +#endif +#ifndef REG_SHELL_GROUP +#define REG_SHELL_GROUP NOTEST +#endif +#ifndef REG_SHELL_PATH +#define REG_SHELL_PATH NOTEST +#endif +#ifndef REG_SPAN +#define REG_SPAN NOTEST +#endif + +#define REG_UNKNOWN (-1) + +#ifndef REG_ENEWLINE +#define REG_ENEWLINE (REG_UNKNOWN-1) +#endif +#ifndef REG_ENULL +#ifndef REG_EMPTY +#define REG_ENULL (REG_UNKNOWN-2) +#else +#define REG_ENULL REG_EMPTY +#endif +#endif +#ifndef REG_ECOUNT +#define REG_ECOUNT (REG_UNKNOWN-3) +#endif +#ifndef REG_BADESC +#define REG_BADESC (REG_UNKNOWN-4) +#endif +#ifndef REG_EMEM +#define REG_EMEM (REG_UNKNOWN-5) +#endif +#ifndef REG_EHUNG +#define REG_EHUNG (REG_UNKNOWN-6) +#endif +#ifndef REG_EBUS +#define REG_EBUS (REG_UNKNOWN-7) +#endif +#ifndef REG_EFAULT +#define REG_EFAULT (REG_UNKNOWN-8) +#endif +#ifndef REG_EFLAGS +#define REG_EFLAGS (REG_UNKNOWN-9) +#endif +#ifndef REG_EDELIM +#define REG_EDELIM (REG_UNKNOWN-9) +#endif + +static const struct { int code; char* name; } codes[] = +{ + REG_UNKNOWN, "UNKNOWN", + REG_NOMATCH, "NOMATCH", + REG_BADPAT, "BADPAT", + REG_ECOLLATE, "ECOLLATE", + REG_ECTYPE, "ECTYPE", + REG_EESCAPE, "EESCAPE", + REG_ESUBREG, "ESUBREG", + REG_EBRACK, "EBRACK", + REG_EPAREN, "EPAREN", + REG_EBRACE, "EBRACE", + REG_BADBR, "BADBR", + REG_ERANGE, "ERANGE", + REG_ESPACE, "ESPACE", + REG_BADRPT, "BADRPT", + REG_ENEWLINE, "ENEWLINE", + REG_ENULL, "ENULL", + REG_ECOUNT, "ECOUNT", + REG_BADESC, "BADESC", + REG_EMEM, "EMEM", + REG_EHUNG, "EHUNG", + REG_EBUS, "EBUS", + REG_EFAULT, "EFAULT", + REG_EFLAGS, "EFLAGS", + REG_EDELIM, "EDELIM", +}; + +static struct +{ + regmatch_t NOMATCH; + int errors; + int extracted; + int ignored; + int lineno; + int passed; + int signals; + int unspecified; + int verify; + int warnings; + char* file; + char* stack; + char* which; + jmp_buf gotcha; +#ifdef REG_DISCIPLINE + Disc_t disc; +#endif +} state; + +static void +quote(char* s, int len, unsigned long test) +{ + unsigned char* u = (unsigned char*)s; + unsigned char* e; + int c; +#ifdef MB_CUR_MAX + int w; +#endif + + if (!u) + printf("NIL"); + else if (!*u && len <= 1) + printf("NULL"); + else if (test & TEST_EXPAND) + { + if (len < 0) + len = strlen((char*)u); + e = u + len; + if (test & TEST_DELIMIT) + printf("\""); + while (u < e) + switch (c = *u++) + { + case '\\': + printf("\\\\"); + break; + case '"': + if (test & TEST_DELIMIT) + printf("\\\""); + else + printf("\""); + break; + case '\a': + printf("\\a"); + break; + case '\b': + printf("\\b"); + break; + case 033: + printf("\\e"); + break; + case '\f': + printf("\\f"); + break; + case '\n': + printf("\\n"); + break; + case '\r': + printf("\\r"); + break; + case '\t': + printf("\\t"); + break; + case '\v': + printf("\\v"); + break; + default: +#ifdef MB_CUR_MAX + s = (char*)u - 1; + if ((w = mblen(s, (char*)e - s)) > 1) + { + u += w - 1; + fwrite(s, 1, w, stdout); + } + else +#endif + if (!iscntrl(c) && isprint(c)) + putchar(c); + else + printf("\\x%02x", c); + break; + } + if (test & TEST_DELIMIT) + printf("\""); + } + else + printf("%s", s); +} + +static void +report(char* comment, char* fun, char* re, char* s, int len, char* msg, int flags, unsigned long test) +{ + if (state.file) + printf("%s:", state.file); + printf("%d:", state.lineno); + if (re) + { + printf(" "); + quote(re, -1, test|TEST_DELIMIT); + if (s) + { + printf(" versus "); + quote(s, len, test|TEST_DELIMIT); + } + } + if (test & TEST_UNSPECIFIED) + { + state.unspecified++; + printf(" unspecified behavior"); + } + else + state.errors++; + if (state.which) + printf(" %s", state.which); + if (flags & REG_NOSUB) + printf(" NOSUB"); + if (fun) + printf(" %s", fun); + if (comment[strlen(comment)-1] == '\n') + printf(" %s", comment); + else + { + printf(" %s: ", comment); + if (msg) + printf("%s: ", msg); + } +} + +static void +error(regex_t* preg, int code) +{ + char* msg; + char buf[256]; + + switch (code) + { + case REG_EBUS: + msg = "bus error"; + break; + case REG_EFAULT: + msg = "memory fault"; + break; + case REG_EHUNG: + msg = "did not terminate"; + break; + default: + regerror(code, preg, msg = buf, sizeof buf); + break; + } + printf("%s\n", msg); +} + +static void +bad(char* comment, char* re, char* s, int len, unsigned long test) +{ + printf("bad test case "); + report(comment, NiL, re, s, len, NiL, 0, test); + exit(1); +} + +static int +escape(char* s) +{ + char* b; + char* t; + char* q; + char* e; + int c; + + for (b = t = s; *t = *s; s++, t++) + if (*s == '\\') + switch (*++s) + { + case '\\': + break; + case 'a': + *t = '\a'; + break; + case 'b': + *t = '\b'; + break; + case 'c': + if (*t = *++s) + *t &= 037; + else + s--; + break; + case 'e': + case 'E': + *t = 033; + break; + case 'f': + *t = '\f'; + break; + case 'n': + *t = '\n'; + break; + case 'r': + *t = '\r'; + break; + case 's': + *t = ' '; + break; + case 't': + *t = '\t'; + break; + case 'v': + *t = '\v'; + break; + case 'u': + case 'x': + c = 0; + q = c == 'u' ? (s + 5) : (char*)0; + e = s + 1; + while (!e || !q || s < q) + { + switch (*++s) + { + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + c = (c << 4) + *s - 'a' + 10; + continue; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + c = (c << 4) + *s - 'A' + 10; + continue; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + c = (c << 4) + *s - '0'; + continue; + case '{': + case '[': + if (s != e) + { + s--; + break; + } + e = 0; + continue; + case '}': + case ']': + if (e) + s--; + break; + default: + s--; + break; + } + break; + } + *t = c; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c = *s - '0'; + q = s + 2; + while (s < q) + { + switch (*++s) + { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c = (c << 3) + *s - '0'; + break; + default: + q = --s; + break; + } + } + *t = c; + break; + default: + *(s + 1) = 0; + bad("invalid C \\ escape\n", s - 1, NiL, 0, 0); + } + return t - b; +} + +static void +matchoffprint(int off) +{ + switch (off) + { + case -2: + printf("X"); + break; + case -1: + printf("?"); + break; + default: + printf("%d", off); + break; + } +} + +static void +matchprint(regmatch_t* match, int nmatch, int nsub, char* ans, unsigned long test) +{ + int i; + + for (; nmatch > nsub + 1; nmatch--) + if ((match[nmatch-1].rm_so != -1 || match[nmatch-1].rm_eo != -1) && (!(test & TEST_IGNORE_POSITION) || match[nmatch-1].rm_so >= 0 && match[nmatch-1].rm_eo >= 0)) + break; + for (i = 0; i < nmatch; i++) + { + printf("("); + matchoffprint(match[i].rm_so); + printf(","); + matchoffprint(match[i].rm_eo); + printf(")"); + } + if (!(test & (TEST_ACTUAL|TEST_BASELINE))) + { + if (ans) + printf(" expected: %s", ans); + printf("\n"); + } +} + +static int +matchcheck(regmatch_t* match, int nmatch, int nsub, char* ans, char* re, char* s, int len, int flags, unsigned long test) +{ + char* p; + int i; + int m; + int n; + + if (streq(ans, "OK")) + return test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY); + for (i = 0, p = ans; i < nmatch && *p; i++) + { + if (*p == '{') + { +#ifdef REG_DISCIPLINE + char* x; + + if (!(x = sfstruse(state.disc.sp))) + bad("out of space [discipline string]\n", NiL, NiL, 0, 0); + if (strcmp(p, x)) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + return 0; + report("callout failed", NiL, re, s, len, NiL, flags, test); + quote(p, -1, test); + printf(" expected, "); + quote(x, -1, test); + printf(" returned\n"); + } +#endif + break; + } + if (*p++ != '(') + bad("improper answer\n", re, s, -1, test); + if (*p == '?') + { + m = -1; + p++; + } + else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10)) + { + m = RE_DUP_MAX; + p += 10; + if (*p == '+' || *p == '-') + m += strtol(p, &p, 10); + } + else + m = strtol(p, &p, 10); + if (*p++ != ',') + bad("improper answer\n", re, s, -1, test); + if (*p == '?') + { + n = -1; + p++; + } + else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10)) + { + n = RE_DUP_MAX; + p += 10; + if (*p == '+' || *p == '-') + n += strtol(p, &p, 10); + } + else + n = strtol(p, &p, 10); + if (*p++ != ')') + bad("improper answer\n", re, s, -1, test); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***