...

Text file src/regexp/testdata/testregex.c

Documentation: regexp/testdata

     1#pragma prototyped noticed
     2
     3/*
     4 * regex(3) test harness
     5 *
     6 * build:	cc -o testregex testregex.c
     7 * help:	testregex --man
     8 * note:	REG_* features are detected by #ifdef; if REG_* are enums
     9 *		then supply #define REG_foo REG_foo for each enum REG_foo
    10 *
    11 *	Glenn Fowler <gsf@research.att.com>
    12 *	AT&T Research
    13 *
    14 * PLEASE: publish your tests so everyone can benefit
    15 *
    16 * The following license covers testregex.c and all associated test data.
    17 *
    18 * Permission is hereby granted, free of charge, to any person obtaining a
    19 * copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software
    20 * without restriction, including without limitation the rights to use,
    21 * copy, modify, merge, publish, distribute, and/or sell copies of the
    22 * Software, and to permit persons to whom the Software is furnished to do
    23 * so, subject to the following disclaimer:
    24 *
    25 * THIS SOFTWARE IS PROVIDED BY AT&T ``AS IS'' AND ANY EXPRESS OR IMPLIED
    26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    28 * IN NO EVENT SHALL AT&T BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    35 */
    36
    37static const char id[] = "\n@(#)$Id: testregex (AT&T Research) 2010-06-10 $\0\n";
    38
    39#if _PACKAGE_ast
    40#include <ast.h>
    41#else
    42#include <sys/types.h>
    43#endif
    44
    45#include <stdio.h>
    46#include <regex.h>
    47#include <ctype.h>
    48#include <setjmp.h>
    49#include <signal.h>
    50#include <string.h>
    51#include <unistd.h>
    52
    53#ifdef	__STDC__
    54#include <stdlib.h>
    55#include <locale.h>
    56#endif
    57
    58#ifndef RE_DUP_MAX
    59#define RE_DUP_MAX	32767
    60#endif
    61
    62#if !_PACKAGE_ast
    63#undef	REG_DISCIPLINE
    64#endif
    65
    66#ifndef REG_DELIMITED
    67#undef	_REG_subcomp
    68#endif
    69
    70#define TEST_ARE		0x00000001
    71#define TEST_BRE		0x00000002
    72#define TEST_ERE		0x00000004
    73#define TEST_KRE		0x00000008
    74#define TEST_LRE		0x00000010
    75#define TEST_SRE		0x00000020
    76
    77#define TEST_EXPAND		0x00000100
    78#define TEST_LENIENT		0x00000200
    79
    80#define TEST_QUERY		0x00000400
    81#define TEST_SUB		0x00000800
    82#define TEST_UNSPECIFIED	0x00001000
    83#define TEST_VERIFY		0x00002000
    84#define TEST_AND		0x00004000
    85#define TEST_OR			0x00008000
    86
    87#define TEST_DELIMIT		0x00010000
    88#define TEST_OK			0x00020000
    89#define TEST_SAME		0x00040000
    90
    91#define TEST_ACTUAL		0x00100000
    92#define TEST_BASELINE		0x00200000
    93#define TEST_FAIL		0x00400000
    94#define TEST_PASS		0x00800000
    95#define TEST_SUMMARY		0x01000000
    96
    97#define TEST_IGNORE_ERROR	0x02000000
    98#define TEST_IGNORE_OVER	0x04000000
    99#define TEST_IGNORE_POSITION	0x08000000
   100
   101#define TEST_CATCH		0x10000000
   102#define TEST_VERBOSE		0x20000000
   103
   104#define TEST_DECOMP		0x40000000
   105
   106#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)
   107
   108#ifdef REG_DISCIPLINE
   109
   110
   111#include <stk.h>
   112
   113typedef struct Disc_s
   114{
   115	regdisc_t	disc;
   116	int		ordinal;
   117	Sfio_t*		sp;
   118} Disc_t;
   119
   120static void*
   121compf(const regex_t* re, const char* xstr, size_t xlen, regdisc_t* disc)
   122{
   123	Disc_t*		dp = (Disc_t*)disc;
   124
   125	return (void*)((char*)0 + ++dp->ordinal);
   126}
   127
   128static int
   129execf(const regex_t* re, void* data, const char* xstr, size_t xlen, const char* sstr, size_t slen, char** snxt, regdisc_t* disc)
   130{
   131	Disc_t*		dp = (Disc_t*)disc;
   132
   133	sfprintf(dp->sp, "{%-.*s}(%lu:%d)", xlen, xstr, (char*)data - (char*)0, slen);
   134	return atoi(xstr);
   135}
   136
   137static void*
   138resizef(void* handle, void* data, size_t size)
   139{
   140	if (!size)
   141		return 0;
   142	return stkalloc((Sfio_t*)handle, size);
   143}
   144
   145#endif
   146
   147#ifndef NiL
   148#ifdef	__STDC__
   149#define NiL		0
   150#else
   151#define NiL		(char*)0
   152#endif
   153#endif
   154
   155#define H(x)		do{if(html)fprintf(stderr,x);}while(0)
   156#define T(x)		fprintf(stderr,x)
   157
   158static void
   159help(int html)
   160{
   161H("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n");
   162H("<HTML>\n");
   163H("<HEAD>\n");
   164H("<TITLE>testregex man document</TITLE>\n");
   165H("</HEAD>\n");
   166H("<BODY bgcolor=white>\n");
   167H("<PRE>\n");
   168T("NAME\n");
   169T("  testregex - regex(3) test harness\n");
   170T("\n");
   171T("SYNOPSIS\n");
   172T("  testregex [ options ]\n");
   173T("\n");
   174T("DESCRIPTION\n");
   175T("  testregex reads regex(3) test specifications, one per line, from the\n");
   176T("  standard input and writes one output line for each failed test. A\n");
   177T("  summary line is written after all tests are done. Each successful\n");
   178T("  test is run again with REG_NOSUB. Unsupported features are noted\n");
   179T("  before the first test, and tests requiring these features are\n");
   180T("  silently ignored.\n");
   181T("\n");
   182T("OPTIONS\n");
   183T("  -c	catch signals and non-terminating calls\n");
   184T("  -e	ignore error return mismatches\n");
   185T("  -h	list help on standard error\n");
   186T("  -n	do not repeat successful tests with regnexec()\n");
   187T("  -o	ignore match[] overrun errors\n");
   188T("  -p	ignore negative position mismatches\n");
   189T("  -s	use stack instead of malloc\n");
   190T("  -x	do not repeat successful tests with REG_NOSUB\n");
   191T("  -v	list each test line\n");
   192T("  -A	list failed test lines with actual answers\n");
   193T("  -B	list all test lines with actual answers\n");
   194T("  -F	list failed test lines\n");
   195T("  -P	list passed test lines\n");
   196T("  -S	output one summary line\n");
   197T("\n");
   198T("INPUT FORMAT\n");
   199T("  Input lines may be blank, a comment beginning with #, or a test\n");
   200T("  specification. A specification is five fields separated by one\n");
   201T("  or more tabs. NULL denotes the empty string and NIL denotes the\n");
   202T("  0 pointer.\n");
   203T("\n");
   204T("  Field 1: the regex(3) flags to apply, one character per REG_feature\n");
   205T("  flag. The test is skipped if REG_feature is not supported by the\n");
   206T("  implementation. If the first character is not [BEASKLP] then the\n");
   207T("  specification is a global control line. One or more of [BEASKLP] may be\n");
   208T("  specified; the test will be repeated for each mode.\n");
   209T("\n");
   210T("    B 	basic			BRE	(grep, ed, sed)\n");
   211T("    E 	REG_EXTENDED		ERE	(egrep)\n");
   212T("    A	REG_AUGMENTED		ARE	(egrep with negation)\n");
   213T("    S	REG_SHELL		SRE	(sh glob)\n");
   214T("    K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)\n");
   215T("    L	REG_LITERAL		LRE	(fgrep)\n");
   216T("\n");
   217T("    a	REG_LEFT|REG_RIGHT	implicit ^...$\n");
   218T("    b	REG_NOTBOL		lhs does not match ^\n");
   219T("    c	REG_COMMENT		ignore space and #...\\n\n");
   220T("    d	REG_SHELL_DOT		explicit leading . match\n");
   221T("    e	REG_NOTEOL		rhs does not match $\n");
   222T("    f	REG_MULTIPLE		multiple \\n separated patterns\n");
   223T("    g	FNM_LEADING_DIR		testfnmatch only -- match until /\n");
   224T("    h	REG_MULTIREF		multiple digit backref\n");
   225T("    i	REG_ICASE		ignore case\n");
   226T("    j	REG_SPAN		. matches \\n\n");
   227T("    k	REG_ESCAPE		\\ to ecape [...] delimiter\n");
   228T("    l	REG_LEFT		implicit ^...\n");
   229T("    m	REG_MINIMAL		minimal match\n");
   230T("    n	REG_NEWLINE		explicit \\n match\n");
   231T("    o	REG_ENCLOSED		(|&) magic inside [@|&](...)\n");
   232T("    p	REG_SHELL_PATH		explicit / match\n");
   233T("    q	REG_DELIMITED		delimited pattern\n");
   234T("    r	REG_RIGHT		implicit ...$\n");
   235T("    s	REG_SHELL_ESCAPED	\\ not special\n");
   236T("    t	REG_MUSTDELIM		all delimiters must be specified\n");
   237T("    u	standard unspecified behavior -- errors not counted\n");
   238T("    v	REG_CLASS_ESCAPE	\\ special inside [...]\n");
   239T("    w	REG_NOSUB		no subexpression match array\n");
   240T("    x	REG_LENIENT		let some errors slide\n");
   241T("    y	REG_LEFT		regexec() implicit ^...\n");
   242T("    z	REG_NULL		NULL subexpressions ok\n");
   243T("    $	                        expand C \\c escapes in fields 2 and 3\n");
   244T("    /	                        field 2 is a regsubcomp() expression\n");
   245T("    =	                        field 3 is a regdecomp() expression\n");
   246T("\n");
   247T("  Field 1 control lines:\n");
   248T("\n");
   249T("    C		set LC_COLLATE and LC_CTYPE to locale in field 2\n");
   250T("\n");
   251T("    ?test ...	output field 5 if passed and != EXPECTED, silent otherwise\n");
   252T("    &test ...	output field 5 if current and previous passed\n");
   253T("    |test ...	output field 5 if current passed and previous failed\n");
   254T("    ; ...	output field 2 if previous failed\n");
   255T("    {test ...	skip if failed until }\n");
   256T("    }		end of skip\n");
   257T("\n");
   258T("    : comment		comment copied as output NOTE\n");
   259T("    :comment:test	:comment: ignored\n");
   260T("    N[OTE] comment	comment copied as output NOTE\n");
   261T("    T[EST] comment	comment\n");
   262T("\n");
   263T("    number		use number for nmatch (20 by default)\n");
   264T("\n");
   265T("  Field 2: the regular expression pattern; SAME uses the pattern from\n");
   266T("    the previous specification. RE_DUP_MAX inside {...} expands to the\n");
   267T("    value from <limits.h>.\n");
   268T("\n");
   269T("  Field 3: the string to match. X...{RE_DUP_MAX} expands to RE_DUP_MAX\n");
   270T("    copies of X.\n");
   271T("\n");
   272T("  Field 4: the test outcome. This is either one of the posix error\n");
   273T("    codes (with REG_ omitted) or the match array, a list of (m,n)\n");
   274T("    entries with m and n being first and last+1 positions in the\n");
   275T("    field 3 string, or NULL if REG_NOSUB is in effect and success\n");
   276T("    is expected. BADPAT is acceptable in place of any regcomp(3)\n");
   277T("    error code. The match[] array is initialized to (-2,-2) before\n");
   278T("    each test. All array elements from 0 to nmatch-1 must be specified\n");
   279T("    in the outcome. Unspecified endpoints (offset -1) are denoted by ?.\n");
   280T("    Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a\n");
   281T("    matched (?{...}) expression, where x is the text enclosed by {...},\n");
   282T("    o is the expression ordinal counting from 1, and n is the length of\n");
   283T("    the unmatched portion of the subject string. If x starts with a\n");
   284T("    number then that is the return value of re_execf(), otherwise 0 is\n");
   285T("    returned. RE_DUP_MAX[-+]N expands to the <limits.h> value -+N.\n");
   286T("\n");
   287T("  Field 5: optional comment appended to the report.\n");
   288T("\n");
   289T("CAVEAT\n");
   290T("    If a regex implementation misbehaves with memory then all bets are off.\n");
   291T("\n");
   292T("CONTRIBUTORS\n");
   293T("  Glenn Fowler    gsf@research.att.com        (ksh strmatch, regex extensions)\n");
   294T("  David Korn      dgk@research.att.com        (ksh glob matcher)\n");
   295T("  Doug McIlroy    mcilroy@dartmouth.edu       (ast regex/testre in C++)\n");
   296T("  Tom Lord        lord@regexps.com            (rx tests)\n");
   297T("  Henry Spencer   henry@zoo.toronto.edu       (original public regex)\n");
   298T("  Andrew Hume     andrew@research.att.com     (gre tests)\n");
   299T("  John Maddock    John_Maddock@compuserve.com (regex++ tests)\n");
   300T("  Philip Hazel    ph10@cam.ac.uk              (pcre tests)\n");
   301T("  Ville Laurikari vl@iki.fi                   (libtre tests)\n");
   302H("</PRE>\n");
   303H("</BODY>\n");
   304H("</HTML>\n");
   305}
   306
   307#ifndef elementsof
   308#define elementsof(x)	(sizeof(x)/sizeof(x[0]))
   309#endif
   310
   311#ifndef streq
   312#define streq(a,b)	(*(a)==*(b)&&!strcmp(a,b))
   313#endif
   314
   315#define HUNG		2
   316#define NOTEST		(~0)
   317
   318#ifndef REG_TEST_DEFAULT
   319#define REG_TEST_DEFAULT	0
   320#endif
   321
   322#ifndef REG_EXEC_DEFAULT
   323#define REG_EXEC_DEFAULT	0
   324#endif
   325
   326static const char* unsupported[] =
   327{
   328	"BASIC",
   329#ifndef REG_EXTENDED
   330	"EXTENDED",
   331#endif
   332#ifndef REG_AUGMENTED
   333	"AUGMENTED",
   334#endif
   335#ifndef REG_SHELL
   336	"SHELL",
   337#endif
   338
   339#ifndef REG_CLASS_ESCAPE
   340	"CLASS_ESCAPE",
   341#endif
   342#ifndef REG_COMMENT
   343	"COMMENT",
   344#endif
   345#ifndef REG_DELIMITED
   346	"DELIMITED",
   347#endif
   348#ifndef REG_DISCIPLINE
   349	"DISCIPLINE",
   350#endif
   351#ifndef REG_ESCAPE
   352	"ESCAPE",
   353#endif
   354#ifndef REG_ICASE
   355	"ICASE",
   356#endif
   357#ifndef REG_LEFT
   358	"LEFT",
   359#endif
   360#ifndef REG_LENIENT
   361	"LENIENT",
   362#endif
   363#ifndef REG_LITERAL
   364	"LITERAL",
   365#endif
   366#ifndef REG_MINIMAL
   367	"MINIMAL",
   368#endif
   369#ifndef REG_MULTIPLE
   370	"MULTIPLE",
   371#endif
   372#ifndef REG_MULTIREF
   373	"MULTIREF",
   374#endif
   375#ifndef REG_MUSTDELIM
   376	"MUSTDELIM",
   377#endif
   378#ifndef REG_NEWLINE
   379	"NEWLINE",
   380#endif
   381#ifndef REG_NOTBOL
   382	"NOTBOL",
   383#endif
   384#ifndef REG_NOTEOL
   385	"NOTEOL",
   386#endif
   387#ifndef REG_NULL
   388	"NULL",
   389#endif
   390#ifndef REG_RIGHT
   391	"RIGHT",
   392#endif
   393#ifndef REG_SHELL_DOT
   394	"SHELL_DOT",
   395#endif
   396#ifndef REG_SHELL_ESCAPED
   397	"SHELL_ESCAPED",
   398#endif
   399#ifndef REG_SHELL_GROUP
   400	"SHELL_GROUP",
   401#endif
   402#ifndef REG_SHELL_PATH
   403	"SHELL_PATH",
   404#endif
   405#ifndef REG_SPAN
   406	"SPAN",
   407#endif
   408#if REG_NOSUB & REG_TEST_DEFAULT
   409	"SUBMATCH",
   410#endif
   411#if !_REG_nexec
   412	"regnexec",
   413#endif
   414#if !_REG_subcomp
   415	"regsubcomp",
   416#endif
   417#if !_REG_decomp
   418	"redecomp",
   419#endif
   420	0
   421};
   422
   423#ifndef REG_CLASS_ESCAPE
   424#define REG_CLASS_ESCAPE	NOTEST
   425#endif
   426#ifndef REG_COMMENT
   427#define REG_COMMENT	NOTEST
   428#endif
   429#ifndef REG_DELIMITED
   430#define REG_DELIMITED	NOTEST
   431#endif
   432#ifndef REG_ESCAPE
   433#define REG_ESCAPE	NOTEST
   434#endif
   435#ifndef REG_ICASE
   436#define REG_ICASE	NOTEST
   437#endif
   438#ifndef REG_LEFT
   439#define REG_LEFT	NOTEST
   440#endif
   441#ifndef REG_LENIENT
   442#define REG_LENIENT	0
   443#endif
   444#ifndef REG_MINIMAL
   445#define REG_MINIMAL	NOTEST
   446#endif
   447#ifndef REG_MULTIPLE
   448#define REG_MULTIPLE	NOTEST
   449#endif
   450#ifndef REG_MULTIREF
   451#define REG_MULTIREF	NOTEST
   452#endif
   453#ifndef REG_MUSTDELIM
   454#define REG_MUSTDELIM	NOTEST
   455#endif
   456#ifndef REG_NEWLINE
   457#define REG_NEWLINE	NOTEST
   458#endif
   459#ifndef REG_NOTBOL
   460#define REG_NOTBOL	NOTEST
   461#endif
   462#ifndef REG_NOTEOL
   463#define REG_NOTEOL	NOTEST
   464#endif
   465#ifndef REG_NULL
   466#define REG_NULL	NOTEST
   467#endif
   468#ifndef REG_RIGHT
   469#define REG_RIGHT	NOTEST
   470#endif
   471#ifndef REG_SHELL_DOT
   472#define REG_SHELL_DOT	NOTEST
   473#endif
   474#ifndef REG_SHELL_ESCAPED
   475#define REG_SHELL_ESCAPED	NOTEST
   476#endif
   477#ifndef REG_SHELL_GROUP
   478#define REG_SHELL_GROUP	NOTEST
   479#endif
   480#ifndef REG_SHELL_PATH
   481#define REG_SHELL_PATH	NOTEST
   482#endif
   483#ifndef REG_SPAN
   484#define REG_SPAN	NOTEST
   485#endif
   486
   487#define REG_UNKNOWN	(-1)
   488
   489#ifndef REG_ENEWLINE
   490#define REG_ENEWLINE	(REG_UNKNOWN-1)
   491#endif
   492#ifndef REG_ENULL
   493#ifndef REG_EMPTY
   494#define REG_ENULL	(REG_UNKNOWN-2)
   495#else
   496#define REG_ENULL	REG_EMPTY
   497#endif
   498#endif
   499#ifndef REG_ECOUNT
   500#define REG_ECOUNT	(REG_UNKNOWN-3)
   501#endif
   502#ifndef REG_BADESC
   503#define REG_BADESC	(REG_UNKNOWN-4)
   504#endif
   505#ifndef REG_EMEM
   506#define REG_EMEM	(REG_UNKNOWN-5)
   507#endif
   508#ifndef REG_EHUNG
   509#define REG_EHUNG	(REG_UNKNOWN-6)
   510#endif
   511#ifndef REG_EBUS
   512#define REG_EBUS	(REG_UNKNOWN-7)
   513#endif
   514#ifndef REG_EFAULT
   515#define REG_EFAULT	(REG_UNKNOWN-8)
   516#endif
   517#ifndef REG_EFLAGS
   518#define REG_EFLAGS	(REG_UNKNOWN-9)
   519#endif
   520#ifndef REG_EDELIM
   521#define REG_EDELIM	(REG_UNKNOWN-9)
   522#endif
   523
   524static const struct { int code; char* name; } codes[] =
   525{
   526	REG_UNKNOWN,	"UNKNOWN",
   527	REG_NOMATCH,	"NOMATCH",
   528	REG_BADPAT,	"BADPAT",
   529	REG_ECOLLATE,	"ECOLLATE",
   530	REG_ECTYPE,	"ECTYPE",
   531	REG_EESCAPE,	"EESCAPE",
   532	REG_ESUBREG,	"ESUBREG",
   533	REG_EBRACK,	"EBRACK",
   534	REG_EPAREN,	"EPAREN",
   535	REG_EBRACE,	"EBRACE",
   536	REG_BADBR,	"BADBR",
   537	REG_ERANGE,	"ERANGE",
   538	REG_ESPACE,	"ESPACE",
   539	REG_BADRPT,	"BADRPT",
   540	REG_ENEWLINE,	"ENEWLINE",
   541	REG_ENULL,	"ENULL",
   542	REG_ECOUNT,	"ECOUNT",
   543	REG_BADESC,	"BADESC",
   544	REG_EMEM,	"EMEM",
   545	REG_EHUNG,	"EHUNG",
   546	REG_EBUS,	"EBUS",
   547	REG_EFAULT,	"EFAULT",
   548	REG_EFLAGS,	"EFLAGS",
   549	REG_EDELIM,	"EDELIM",
   550};
   551
   552static struct
   553{
   554	regmatch_t	NOMATCH;
   555	int		errors;
   556	int		extracted;
   557	int		ignored;
   558	int		lineno;
   559	int		passed;
   560	int		signals;
   561	int		unspecified;
   562	int		verify;
   563	int		warnings;
   564	char*		file;
   565	char*		stack;
   566	char*		which;
   567	jmp_buf		gotcha;
   568#ifdef REG_DISCIPLINE
   569	Disc_t		disc;
   570#endif
   571} state;
   572
   573static void
   574quote(char* s, int len, unsigned long test)
   575{
   576	unsigned char*	u = (unsigned char*)s;
   577	unsigned char*	e;
   578	int		c;
   579#ifdef MB_CUR_MAX
   580	int		w;
   581#endif
   582
   583	if (!u)
   584		printf("NIL");
   585	else if (!*u && len <= 1)
   586		printf("NULL");
   587	else if (test & TEST_EXPAND)
   588	{
   589		if (len < 0)
   590			len = strlen((char*)u);
   591		e = u + len;
   592		if (test & TEST_DELIMIT)
   593			printf("\"");
   594		while (u < e)
   595			switch (c = *u++)
   596			{
   597			case '\\':
   598				printf("\\\\");
   599				break;
   600			case '"':
   601				if (test & TEST_DELIMIT)
   602					printf("\\\"");
   603				else
   604					printf("\"");
   605				break;
   606			case '\a':
   607				printf("\\a");
   608				break;
   609			case '\b':
   610				printf("\\b");
   611				break;
   612			case 033:
   613				printf("\\e");
   614				break;
   615			case '\f':
   616				printf("\\f");
   617				break;
   618			case '\n':
   619				printf("\\n");
   620				break;
   621			case '\r':
   622				printf("\\r");
   623				break;
   624			case '\t':
   625				printf("\\t");
   626				break;
   627			case '\v':
   628				printf("\\v");
   629				break;
   630			default:
   631#ifdef MB_CUR_MAX
   632				s = (char*)u - 1;
   633				if ((w = mblen(s, (char*)e - s)) > 1)
   634				{
   635					u += w - 1;
   636					fwrite(s, 1, w, stdout);
   637				}
   638				else
   639#endif
   640				if (!iscntrl(c) && isprint(c))
   641					putchar(c);
   642				else
   643					printf("\\x%02x", c);
   644				break;
   645			}
   646		if (test & TEST_DELIMIT)
   647			printf("\"");
   648	}
   649	else
   650		printf("%s", s);
   651}
   652
   653static void
   654report(char* comment, char* fun, char* re, char* s, int len, char* msg, int flags, unsigned long test)
   655{
   656	if (state.file)
   657		printf("%s:", state.file);
   658	printf("%d:", state.lineno);
   659	if (re)
   660	{
   661		printf(" ");
   662		quote(re, -1, test|TEST_DELIMIT);
   663		if (s)
   664		{
   665			printf(" versus ");
   666			quote(s, len, test|TEST_DELIMIT);
   667		}
   668	}
   669	if (test & TEST_UNSPECIFIED)
   670	{
   671		state.unspecified++;
   672		printf(" unspecified behavior");
   673	}
   674	else
   675		state.errors++;
   676	if (state.which)
   677		printf(" %s", state.which);
   678	if (flags & REG_NOSUB)
   679		printf(" NOSUB");
   680	if (fun)
   681		printf(" %s", fun);
   682	if (comment[strlen(comment)-1] == '\n')
   683		printf(" %s", comment);
   684	else
   685	{
   686		printf(" %s: ", comment);
   687		if (msg)
   688			printf("%s: ", msg);
   689	}
   690}
   691
   692static void
   693error(regex_t* preg, int code)
   694{
   695	char*	msg;
   696	char	buf[256];
   697
   698	switch (code)
   699	{
   700	case REG_EBUS:
   701		msg = "bus error";
   702		break;
   703	case REG_EFAULT:
   704		msg = "memory fault";
   705		break;
   706	case REG_EHUNG:
   707		msg = "did not terminate";
   708		break;
   709	default:
   710		regerror(code, preg, msg = buf, sizeof buf);
   711		break;
   712	}
   713	printf("%s\n", msg);
   714}
   715
   716static void
   717bad(char* comment, char* re, char* s, int len, unsigned long test)
   718{
   719	printf("bad test case ");
   720	report(comment, NiL, re, s, len, NiL, 0, test);
   721	exit(1);
   722}
   723
   724static int
   725escape(char* s)
   726{
   727	char*	b;
   728	char*	t;
   729	char*	q;
   730	char*	e;
   731	int	c;
   732
   733	for (b = t = s; *t = *s; s++, t++)
   734		if (*s == '\\')
   735			switch (*++s)
   736			{
   737			case '\\':
   738				break;
   739			case 'a':
   740				*t = '\a';
   741				break;
   742			case 'b':
   743				*t = '\b';
   744				break;
   745			case 'c':
   746				if (*t = *++s)
   747					*t &= 037;
   748				else
   749					s--;
   750				break;
   751			case 'e':
   752			case 'E':
   753				*t = 033;
   754				break;
   755			case 'f':
   756				*t = '\f';
   757				break;
   758			case 'n':
   759				*t = '\n';
   760				break;
   761			case 'r':
   762				*t = '\r';
   763				break;
   764			case 's':
   765				*t = ' ';
   766				break;
   767			case 't':
   768				*t = '\t';
   769				break;
   770			case 'v':
   771				*t = '\v';
   772				break;
   773			case 'u':
   774			case 'x':
   775				c = 0;
   776				q = c == 'u' ? (s + 5) : (char*)0;
   777				e = s + 1;
   778				while (!e || !q || s < q)
   779				{
   780					switch (*++s)
   781					{
   782					case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
   783						c = (c << 4) + *s - 'a' + 10;
   784						continue;
   785					case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
   786						c = (c << 4) + *s - 'A' + 10;
   787						continue;
   788					case '0': case '1': case '2': case '3': case '4':
   789					case '5': case '6': case '7': case '8': case '9':
   790						c = (c << 4) + *s - '0';
   791						continue;
   792					case '{':
   793					case '[':
   794						if (s != e)
   795						{
   796							s--;
   797							break;
   798						}
   799						e = 0;
   800						continue;
   801					case '}':
   802					case ']':
   803						if (e)
   804							s--;
   805						break;
   806					default:
   807						s--;
   808						break;
   809					}
   810					break;
   811				}
   812				*t = c;
   813				break;
   814			case '0': case '1': case '2': case '3':
   815			case '4': case '5': case '6': case '7':
   816				c = *s - '0';
   817				q = s + 2;
   818				while (s < q)
   819				{
   820					switch (*++s)
   821					{
   822					case '0': case '1': case '2': case '3':
   823					case '4': case '5': case '6': case '7':
   824						c = (c << 3) + *s - '0';
   825						break;
   826					default:
   827						q = --s;
   828						break;
   829					}
   830				}
   831				*t = c;
   832				break;
   833			default:
   834				*(s + 1) = 0;
   835				bad("invalid C \\ escape\n", s - 1, NiL, 0, 0);
   836			}
   837	return t - b;
   838}
   839
   840static void
   841matchoffprint(int off)
   842{
   843	switch (off)
   844	{
   845	case -2:
   846		printf("X");
   847		break;
   848	case -1:
   849		printf("?");
   850		break;
   851	default:
   852		printf("%d", off);
   853		break;
   854	}
   855}
   856
   857static void
   858matchprint(regmatch_t* match, int nmatch, int nsub, char* ans, unsigned long test)
   859{
   860	int	i;
   861
   862	for (; nmatch > nsub + 1; nmatch--)
   863		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))
   864			break;
   865	for (i = 0; i < nmatch; i++)
   866	{
   867		printf("(");
   868		matchoffprint(match[i].rm_so);
   869		printf(",");
   870		matchoffprint(match[i].rm_eo);
   871		printf(")");
   872	}
   873	if (!(test & (TEST_ACTUAL|TEST_BASELINE)))
   874	{
   875		if (ans)
   876			printf(" expected: %s", ans);
   877		printf("\n");
   878	}
   879}
   880
   881static int
   882matchcheck(regmatch_t* match, int nmatch, int nsub, char* ans, char* re, char* s, int len, int flags, unsigned long test)
   883{
   884	char*	p;
   885	int	i;
   886	int	m;
   887	int	n;
   888
   889	if (streq(ans, "OK"))
   890		return test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY);
   891	for (i = 0, p = ans; i < nmatch && *p; i++)
   892	{
   893		if (*p == '{')
   894		{
   895#ifdef REG_DISCIPLINE
   896			char*	x;
   897
   898			if (!(x = sfstruse(state.disc.sp)))
   899				bad("out of space [discipline string]\n", NiL, NiL, 0, 0);
   900			if (strcmp(p, x))
   901			{
   902				if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
   903					return 0;
   904				report("callout failed", NiL, re, s, len, NiL, flags, test);
   905				quote(p, -1, test);
   906				printf(" expected, ");
   907				quote(x, -1, test);
   908				printf(" returned\n");
   909			}
   910#endif
   911			break;
   912		}
   913		if (*p++ != '(')
   914			bad("improper answer\n", re, s, -1, test);
   915		if (*p == '?')
   916		{
   917			m = -1;
   918			p++;
   919		}
   920		else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10))
   921		{
   922			m = RE_DUP_MAX;
   923			p += 10;
   924			if (*p == '+' || *p == '-')
   925				m += strtol(p, &p, 10);
   926		}
   927		else
   928			m = strtol(p, &p, 10);
   929		if (*p++ != ',')
   930			bad("improper answer\n", re, s, -1, test);
   931		if (*p == '?')
   932		{
   933			n = -1;
   934			p++;
   935		}
   936		else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10))
   937		{
   938			n = RE_DUP_MAX;
   939			p += 10;
   940			if (*p == '+' || *p == '-')
   941				n += strtol(p, &p, 10);
   942		}
   943		else
   944			n = strtol(p, &p, 10);
   945		if (*p++ != ')')
   946			bad("improper answer\n", re, s, -1, test);
   947		if (m!=match[i].rm_so || n!=match[i].rm_eo)
   948		{
   949			if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)))
   950			{
   951				report("failed: match was", NiL, re, s, len, NiL, flags, test);
   952				matchprint(match, nmatch, nsub, ans, test);
   953			}
   954			return 0;
   955		}
   956	}
   957	for (; i < nmatch; i++)
   958	{
   959		if (match[i].rm_so!=-1 || match[i].rm_eo!=-1)
   960		{
   961			if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_VERIFY)))
   962			{
   963				if ((test & TEST_IGNORE_POSITION) && (match[i].rm_so<0 || match[i].rm_eo<0))
   964				{
   965					state.ignored++;
   966					return 0;
   967				}
   968				if (!(test & TEST_SUMMARY))
   969				{
   970					report("failed: match was", NiL, re, s, len, NiL, flags, test);
   971					matchprint(match, nmatch, nsub, ans, test);
   972				}
   973			}
   974			return 0;
   975		}
   976	}
   977	if (!(test & TEST_IGNORE_OVER) && match[nmatch].rm_so != state.NOMATCH.rm_so)
   978	{
   979		if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)))
   980		{
   981			report("failed: overran match array", NiL, re, s, len, NiL, flags, test);
   982			matchprint(match, nmatch + 1, nsub, NiL, test);
   983		}
   984		return 0;
   985	}
   986	return 1;
   987}
   988
   989static void
   990sigunblock(int s)
   991{
   992#ifdef SIG_SETMASK
   993	int		op;
   994	sigset_t	mask;
   995
   996	sigemptyset(&mask);
   997	if (s)
   998	{
   999		sigaddset(&mask, s);
  1000		op = SIG_UNBLOCK;
  1001	}
  1002	else op = SIG_SETMASK;
  1003	sigprocmask(op, &mask, NiL);
  1004#else
  1005#ifdef sigmask
  1006	sigsetmask(s ? (sigsetmask(0L) & ~sigmask(s)) : 0L);
  1007#endif
  1008#endif
  1009}
  1010
  1011static void
  1012gotcha(int sig)
  1013{
  1014	int	ret;
  1015
  1016	signal(sig, gotcha);
  1017	alarm(0);
  1018	state.signals++;
  1019	switch (sig)
  1020	{
  1021	case SIGALRM:
  1022		ret = REG_EHUNG;
  1023		break;
  1024	case SIGBUS:
  1025		ret = REG_EBUS;
  1026		break;
  1027	default:
  1028		ret = REG_EFAULT;
  1029		break;
  1030	}
  1031	sigunblock(sig);
  1032	longjmp(state.gotcha, ret);
  1033}
  1034
  1035static char*
  1036getline(FILE* fp)
  1037{
  1038	static char	buf[32 * 1024];
  1039
  1040	register char*	s = buf;
  1041	register char*	e = &buf[sizeof(buf)];
  1042	register char*	b;
  1043
  1044	for (;;)
  1045	{
  1046		if (!(b = fgets(s, e - s, fp)))
  1047			return 0;
  1048		state.lineno++;
  1049		s += strlen(s);
  1050		if (s == b || *--s != '\n' || s == b || *(s - 1) != '\\')
  1051		{
  1052			*s = 0;
  1053			break;
  1054		}
  1055		s--;
  1056	}
  1057	return buf;
  1058}
  1059
  1060static unsigned long
  1061note(unsigned long level, char* msg, unsigned long skip, unsigned long test)
  1062{
  1063	if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)) && !skip)
  1064	{
  1065		printf("NOTE\t");
  1066		if (msg)
  1067			printf("%s: ", msg);
  1068		printf("skipping lines %d", state.lineno);
  1069	}
  1070	return skip | level;
  1071}
  1072
  1073#define TABS(n)		&ts[7-((n)&7)]
  1074
  1075static char		ts[] = "\t\t\t\t\t\t\t";
  1076
  1077static unsigned long
  1078extract(int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test)
  1079{
  1080	if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_OK|TEST_PASS|TEST_SUMMARY))
  1081	{
  1082		state.extracted = 1;
  1083		if (test & TEST_OK)
  1084		{
  1085			state.passed++;
  1086			if ((test & TEST_VERIFY) && !(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
  1087			{
  1088				if (msg && strcmp(msg, "EXPECTED"))
  1089					printf("NOTE\t%s\n", msg);
  1090				return skip;
  1091			}
  1092			test &= ~(TEST_PASS|TEST_QUERY);
  1093		}
  1094		if (test & (TEST_QUERY|TEST_VERIFY))
  1095		{
  1096			if (test & TEST_BASELINE)
  1097				test &= ~(TEST_BASELINE|TEST_PASS);
  1098			else
  1099				test |= TEST_PASS;
  1100			skip |= level;
  1101		}
  1102		if (!(test & TEST_OK))
  1103		{
  1104			if (test & TEST_UNSPECIFIED)
  1105				state.unspecified++;
  1106			else
  1107				state.errors++;
  1108		}
  1109		if (test & (TEST_PASS|TEST_SUMMARY))
  1110			return skip;
  1111		test &= ~TEST_DELIMIT;
  1112		printf("%s%s", spec, TABS(*tabs++));
  1113		if ((test & (TEST_BASELINE|TEST_SAME)) == (TEST_BASELINE|TEST_SAME))
  1114			printf("SAME");
  1115		else
  1116			quote(re, -1, test);
  1117		printf("%s", TABS(*tabs++));
  1118		quote(s, -1, test);
  1119		printf("%s", TABS(*tabs++));
  1120		if (!(test & (TEST_ACTUAL|TEST_BASELINE)) || !accept && !match)
  1121			printf("%s", ans);
  1122		else if (accept)
  1123			printf("%s", accept);
  1124		else
  1125			matchprint(match, nmatch, nsub, NiL, test);
  1126		if (msg)
  1127			printf("%s%s", TABS(*tabs++), msg);
  1128		putchar('\n');
  1129	}
  1130	else if (test & TEST_QUERY)
  1131		skip = note(level, msg, skip, test);
  1132	else if (test & TEST_VERIFY)
  1133		state.extracted = 1;
  1134	return skip;
  1135}
  1136
  1137static int
  1138catchfree(regex_t* preg, int flags, int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test)
  1139{
  1140	int	eret;
  1141
  1142	if (!(test & TEST_CATCH))
  1143	{
  1144		regfree(preg);
  1145		eret = 0;
  1146	}
  1147	else if (!(eret = setjmp(state.gotcha)))
  1148	{
  1149		alarm(HUNG);
  1150		regfree(preg);
  1151		alarm(0);
  1152	}
  1153	else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  1154		extract(tabs, spec, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
  1155	else
  1156	{
  1157		report("failed", "regfree", re, NiL, -1, msg, flags, test);
  1158		error(preg, eret);
  1159	}
  1160	return eret;
  1161}
  1162
  1163static char*
  1164expand(char* os, char* ot)
  1165{
  1166	char*	s = os;
  1167	char*	t;
  1168	int	n = 0;
  1169	int	r;
  1170	long	m;
  1171
  1172	for (;;)
  1173	{
  1174		switch (*s++)
  1175		{
  1176		case 0:
  1177			break;
  1178		case '{':
  1179			n++;
  1180			continue;
  1181		case '}':
  1182			n--;
  1183			continue;
  1184		case 'R':
  1185			if (n == 1 && !memcmp(s, "E_DUP_MAX", 9))
  1186			{
  1187				s--;
  1188				for (t = ot; os < s; *t++ = *os++);
  1189				r = ((t - ot) >= 5 && t[-1] == '{' && t[-2] == '.' && t[-3] == '.' && t[-4] == '.') ? t[-5] : 0;
  1190				os = ot;
  1191				m = RE_DUP_MAX;
  1192				if (*(s += 10) == '+' || *s == '-')
  1193					m += strtol(s, &s, 10);
  1194				if (r)
  1195				{
  1196					t -= 5;
  1197					while (m-- > 0)
  1198						*t++ = r;
  1199					while (*s && *s++ != '}');
  1200				}
  1201				else
  1202					t += snprintf(t, 32, "%ld", m);
  1203				while (*t = *s++)
  1204					t++;
  1205				break;
  1206			}
  1207			continue;
  1208		default:
  1209			continue;
  1210		}
  1211		break;
  1212	}
  1213	return os;
  1214}
  1215
  1216int
  1217main(int argc, char** argv)
  1218{
  1219	int		flags;
  1220	int		cflags;
  1221	int		eflags;
  1222	int		nmatch;
  1223	int		nexec;
  1224	int		nstr;
  1225	int		cret;
  1226	int		eret;
  1227	int		nsub;
  1228	int		i;
  1229	int		j;
  1230	int		expected;
  1231	int		got;
  1232	int		locale;
  1233	int		subunitlen;
  1234	int		testno;
  1235	unsigned long	level;
  1236	unsigned long	skip;
  1237	char*		p;
  1238	char*		line;
  1239	char*		spec;
  1240	char*		re;
  1241	char*		s;
  1242	char*		ans;
  1243	char*		msg;
  1244	char*		fun;
  1245	char*		ppat;
  1246	char*		subunit;
  1247	char*		version;
  1248	char*		field[6];
  1249	char*		delim[6];
  1250	FILE*		fp;
  1251	int		tabs[6];
  1252	char		unit[64];
  1253	regmatch_t	match[100];
  1254	regex_t		preg;
  1255
  1256	static char	pat[32 * 1024];
  1257	static char	patbuf[32 * 1024];
  1258	static char	strbuf[32 * 1024];
  1259
  1260	int		nonosub = REG_NOSUB == 0;
  1261	int		nonexec = 0;
  1262
  1263	unsigned long	test = 0;
  1264
  1265	static char*	filter[] = { "-", 0 };
  1266
  1267	state.NOMATCH.rm_so = state.NOMATCH.rm_eo = -2;
  1268	p = unit;
  1269	version = (char*)id + 10;
  1270	while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace(*p))
  1271		p++;
  1272	*p = 0;
  1273	while ((p = *++argv) && *p == '-')
  1274		for (;;)
  1275		{
  1276			switch (*++p)
  1277			{
  1278			case 0:
  1279				break;
  1280			case 'c':
  1281				test |= TEST_CATCH;
  1282				continue;
  1283			case 'e':
  1284				test |= TEST_IGNORE_ERROR;
  1285				continue;
  1286			case 'h':
  1287			case '?':
  1288				help(0);
  1289				return 2;
  1290			case '-':
  1291				help(p[1] == 'h');
  1292				return 2;
  1293			case 'n':
  1294				nonexec = 1;
  1295				continue;
  1296			case 'o':
  1297				test |= TEST_IGNORE_OVER;
  1298				continue;
  1299			case 'p':
  1300				test |= TEST_IGNORE_POSITION;
  1301				continue;
  1302			case 's':
  1303#ifdef REG_DISCIPLINE
  1304				if (!(state.stack = stkalloc(stkstd, 0)))
  1305					fprintf(stderr, "%s: out of space [stack]", unit);
  1306				state.disc.disc.re_resizef = resizef;
  1307				state.disc.disc.re_resizehandle = (void*)stkstd;
  1308#endif
  1309				continue;
  1310			case 'x':
  1311				nonosub = 1;
  1312				continue;
  1313			case 'v':
  1314				test |= TEST_VERBOSE;
  1315				continue;
  1316			case 'A':
  1317				test |= TEST_ACTUAL;
  1318				continue;
  1319			case 'B':
  1320				test |= TEST_BASELINE;
  1321				continue;
  1322			case 'F':
  1323				test |= TEST_FAIL;
  1324				continue;
  1325			case 'P':
  1326				test |= TEST_PASS;
  1327				continue;
  1328			case 'S':
  1329				test |= TEST_SUMMARY;
  1330				continue;
  1331			default:
  1332				fprintf(stderr, "%s: %c: invalid option\n", unit, *p);
  1333				return 2;
  1334			}
  1335			break;
  1336		}
  1337	if (!*argv)
  1338		argv = filter;
  1339	locale = 0;
  1340	while (state.file = *argv++)
  1341	{
  1342		if (streq(state.file, "-") || streq(state.file, "/dev/stdin") || streq(state.file, "/dev/fd/0"))
  1343		{
  1344			state.file = 0;
  1345			fp = stdin;
  1346		}
  1347		else if (!(fp = fopen(state.file, "r")))
  1348		{
  1349			fprintf(stderr, "%s: %s: cannot read\n", unit, state.file);
  1350			return 2;
  1351		}
  1352		testno = state.errors = state.ignored = state.lineno = state.passed =
  1353		state.signals = state.unspecified = state.warnings = 0;
  1354		skip = 0;
  1355		level = 1;
  1356		if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
  1357		{
  1358			printf("TEST\t%s ", unit);
  1359			if (s = state.file)
  1360			{
  1361				subunit = p = 0;
  1362				for (;;)
  1363				{
  1364					switch (*s++)
  1365					{
  1366					case 0:
  1367						break;
  1368					case '/':
  1369						subunit = s;
  1370						continue;
  1371					case '.':
  1372						p = s - 1;
  1373						continue;
  1374					default:
  1375						continue;
  1376					}
  1377					break;
  1378				}
  1379				if (!subunit)
  1380					subunit = state.file;
  1381				if (p < subunit)
  1382					p = s - 1;
  1383				subunitlen = p - subunit;
  1384				printf("%-.*s ", subunitlen, subunit);
  1385			}
  1386			else
  1387				subunit = 0;
  1388			for (s = version; *s && (*s != ' ' || *(s + 1) != '$'); s++)
  1389				putchar(*s);
  1390			if (test & TEST_CATCH)
  1391				printf(", catch");
  1392			if (test & TEST_IGNORE_ERROR)
  1393				printf(", ignore error code mismatches");
  1394			if (test & TEST_IGNORE_POSITION)
  1395				printf(", ignore negative position mismatches");
  1396#ifdef REG_DISCIPLINE
  1397			if (state.stack)
  1398				printf(", stack");
  1399#endif
  1400			if (test & TEST_VERBOSE)
  1401				printf(", verbose");
  1402			printf("\n");
  1403#ifdef REG_VERSIONID
  1404			if (regerror(REG_VERSIONID, NiL, pat, sizeof(pat)) > 0)
  1405				s = pat;
  1406			else
  1407#endif
  1408#ifdef REG_TEST_VERSION
  1409			s = REG_TEST_VERSION;
  1410#else
  1411			s = "regex";
  1412#endif
  1413			printf("NOTE\t%s\n", s);
  1414			if (elementsof(unsupported) > 1)
  1415			{
  1416#if (REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) || !defined(REG_EXTENDED)
  1417				i = 0;
  1418#else
  1419				i = REG_EXTENDED != 0;
  1420#endif
  1421				for (got = 0; i < elementsof(unsupported) - 1; i++)
  1422				{
  1423					if (!got)
  1424					{
  1425						got = 1;
  1426						printf("NOTE\tunsupported: %s", unsupported[i]);
  1427					}
  1428					else
  1429						printf(",%s", unsupported[i]);
  1430				}
  1431				if (got)
  1432					printf("\n");
  1433			}
  1434		}
  1435#ifdef REG_DISCIPLINE
  1436		state.disc.disc.re_version = REG_VERSION;
  1437		state.disc.disc.re_compf = compf;
  1438		state.disc.disc.re_execf = execf;
  1439		if (!(state.disc.sp = sfstropen()))
  1440			bad("out of space [discipline string stream]\n", NiL, NiL, 0, 0);
  1441		preg.re_disc = &state.disc.disc;
  1442#endif
  1443		if (test & TEST_CATCH)
  1444		{
  1445			signal(SIGALRM, gotcha);
  1446			signal(SIGBUS, gotcha);
  1447			signal(SIGSEGV, gotcha);
  1448		}
  1449		while (p = getline(fp))
  1450		{
  1451
  1452		/* parse: */
  1453
  1454			line = p;
  1455			if (*p == ':' && !isspace(*(p + 1)))
  1456			{
  1457				while (*++p && *p != ':');
  1458				if (!*p++)
  1459				{
  1460					if (test & TEST_BASELINE)
  1461						printf("%s\n", line);
  1462					continue;
  1463				}
  1464			}
  1465			while (isspace(*p))
  1466				p++;
  1467			if (*p == 0 || *p == '#' || *p == 'T')
  1468			{
  1469				if (test & TEST_BASELINE)
  1470					printf("%s\n", line);
  1471				continue;
  1472			}
  1473			if (*p == ':' || *p == 'N')
  1474			{
  1475				if (test & TEST_BASELINE)
  1476					printf("%s\n", line);
  1477				else if (!(test & (TEST_ACTUAL|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
  1478				{
  1479					while (*++p && !isspace(*p));
  1480					while (isspace(*p))
  1481						p++;
  1482					printf("NOTE	%s\n", p);
  1483				}
  1484				continue;
  1485			}
  1486			j = 0;
  1487			i = 0;
  1488			field[i++] = p;
  1489			for (;;)
  1490			{
  1491				switch (*p++)
  1492				{
  1493				case 0:
  1494					p--;
  1495					j = 0;
  1496					goto checkfield;
  1497				case '\t':
  1498					*(delim[i] = p - 1) = 0;
  1499					j = 1;
  1500				checkfield:
  1501					s = field[i - 1];
  1502					if (streq(s, "NIL"))
  1503						field[i - 1] = 0;
  1504					else if (streq(s, "NULL"))
  1505						*s = 0;
  1506					while (*p == '\t')
  1507					{
  1508						p++;
  1509						j++;
  1510					}
  1511					tabs[i - 1] = j;
  1512					if (!*p)
  1513						break;
  1514					if (i >= elementsof(field))
  1515						bad("too many fields\n", NiL, NiL, 0, 0);
  1516					field[i++] = p;
  1517					/*FALLTHROUGH*/
  1518				default:
  1519					continue;
  1520				}
  1521				break;
  1522			}
  1523			if (!(spec = field[0]))
  1524				bad("NIL spec\n", NiL, NiL, 0, 0);
  1525
  1526		/* interpret: */
  1527
  1528			cflags = REG_TEST_DEFAULT;
  1529			eflags = REG_EXEC_DEFAULT;
  1530			test &= TEST_GLOBAL;
  1531			state.extracted = 0;
  1532			nmatch = 20;
  1533			nsub = -1;
  1534			for (p = spec; *p; p++)
  1535			{
  1536				if (isdigit(*p))
  1537				{
  1538					nmatch = strtol(p, &p, 10);
  1539					if (nmatch >= elementsof(match))
  1540						bad("nmatch must be < 100\n", NiL, NiL, 0, 0);
  1541					p--;
  1542					continue;
  1543				}
  1544				switch (*p)
  1545				{
  1546				case 'A':
  1547					test |= TEST_ARE;
  1548					continue;
  1549				case 'B':
  1550					test |= TEST_BRE;
  1551					continue;
  1552				case 'C':
  1553					if (!(test & TEST_QUERY) && !(skip & level))
  1554						bad("locale must be nested\n", NiL, NiL, 0, 0);
  1555					test &= ~TEST_QUERY;
  1556					if (locale)
  1557						bad("locale nesting not supported\n", NiL, NiL, 0, 0);
  1558					if (i != 2)
  1559						bad("locale field expected\n", NiL, NiL, 0, 0);
  1560					if (!(skip & level))
  1561					{
  1562#if defined(LC_COLLATE) && defined(LC_CTYPE)
  1563						s = field[1];
  1564						if (!s || streq(s, "POSIX"))
  1565							s = "C";
  1566						if ((ans = setlocale(LC_COLLATE, s)) && streq(ans, "POSIX"))
  1567							ans = "C";
  1568						if (!ans || !streq(ans, s) && streq(s, "C"))
  1569							ans = 0;
  1570						else if ((ans = setlocale(LC_CTYPE, s)) && streq(ans, "POSIX"))
  1571							ans = "C";
  1572						if (!ans || !streq(ans, s) && streq(s, "C"))
  1573							skip = note(level, s, skip, test);
  1574						else
  1575						{
  1576							if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
  1577								printf("NOTE	\"%s\" locale\n", s);
  1578							locale = level;
  1579						}
  1580#else
  1581						skip = note(level, skip, test, "locales not supported");
  1582#endif
  1583					}
  1584					cflags = NOTEST;
  1585					continue;
  1586				case 'E':
  1587					test |= TEST_ERE;
  1588					continue;
  1589				case 'K':
  1590					test |= TEST_KRE;
  1591					continue;
  1592				case 'L':
  1593					test |= TEST_LRE;
  1594					continue;
  1595				case 'S':
  1596					test |= TEST_SRE;
  1597					continue;
  1598
  1599				case 'a':
  1600					cflags |= REG_LEFT|REG_RIGHT;
  1601					continue;
  1602				case 'b':
  1603					eflags |= REG_NOTBOL;
  1604					continue;
  1605				case 'c':
  1606					cflags |= REG_COMMENT;
  1607					continue;
  1608				case 'd':
  1609					cflags |= REG_SHELL_DOT;
  1610					continue;
  1611				case 'e':
  1612					eflags |= REG_NOTEOL;
  1613					continue;
  1614				case 'f':
  1615					cflags |= REG_MULTIPLE;
  1616					continue;
  1617				case 'g':
  1618					cflags |= NOTEST;
  1619					continue;
  1620				case 'h':
  1621					cflags |= REG_MULTIREF;
  1622					continue;
  1623				case 'i':
  1624					cflags |= REG_ICASE;
  1625					continue;
  1626				case 'j':
  1627					cflags |= REG_SPAN;
  1628					continue;
  1629				case 'k':
  1630					cflags |= REG_ESCAPE;
  1631					continue;
  1632				case 'l':
  1633					cflags |= REG_LEFT;
  1634					continue;
  1635				case 'm':
  1636					cflags |= REG_MINIMAL;
  1637					continue;
  1638				case 'n':
  1639					cflags |= REG_NEWLINE;
  1640					continue;
  1641				case 'o':
  1642					cflags |= REG_SHELL_GROUP;
  1643					continue;
  1644				case 'p':
  1645					cflags |= REG_SHELL_PATH;
  1646					continue;
  1647				case 'q':
  1648					cflags |= REG_DELIMITED;
  1649					continue;
  1650				case 'r':
  1651					cflags |= REG_RIGHT;
  1652					continue;
  1653				case 's':
  1654					cflags |= REG_SHELL_ESCAPED;
  1655					continue;
  1656				case 't':
  1657					cflags |= REG_MUSTDELIM;
  1658					continue;
  1659				case 'u':
  1660					test |= TEST_UNSPECIFIED;
  1661					continue;
  1662				case 'v':
  1663					cflags |= REG_CLASS_ESCAPE;
  1664					continue;
  1665				case 'w':
  1666					cflags |= REG_NOSUB;
  1667					continue;
  1668				case 'x':
  1669					if (REG_LENIENT)
  1670						cflags |= REG_LENIENT;
  1671					else
  1672						test |= TEST_LENIENT;
  1673					continue;
  1674				case 'y':
  1675					eflags |= REG_LEFT;
  1676					continue;
  1677				case 'z':
  1678					cflags |= REG_NULL;
  1679					continue;
  1680
  1681				case '$':
  1682					test |= TEST_EXPAND;
  1683					continue;
  1684
  1685				case '/':
  1686					test |= TEST_SUB;
  1687					continue;
  1688
  1689				case '=':
  1690					test |= TEST_DECOMP;
  1691					continue;
  1692
  1693				case '?':
  1694					test |= TEST_VERIFY;
  1695					test &= ~(TEST_AND|TEST_OR);
  1696					state.verify = state.passed;
  1697					continue;
  1698				case '&':
  1699					test |= TEST_VERIFY|TEST_AND;
  1700					test &= ~TEST_OR;
  1701					continue;
  1702				case '|':
  1703					test |= TEST_VERIFY|TEST_OR;
  1704					test &= ~TEST_AND;
  1705					continue;
  1706				case ';':
  1707					test |= TEST_OR;
  1708					test &= ~TEST_AND;
  1709					continue;
  1710
  1711				case '{':
  1712					level <<= 1;
  1713					if (skip & (level >> 1))
  1714					{
  1715						skip |= level;
  1716						cflags = NOTEST;
  1717					}
  1718					else
  1719					{
  1720						skip &= ~level;
  1721						test |= TEST_QUERY;
  1722					}
  1723					continue;
  1724				case '}':
  1725					if (level == 1)
  1726						bad("invalid {...} nesting\n", NiL, NiL, 0, 0);
  1727					if ((skip & level) && !(skip & (level>>1)))
  1728					{
  1729						if (!(test & (TEST_BASELINE|TEST_SUMMARY)))
  1730						{
  1731							if (test & (TEST_ACTUAL|TEST_FAIL))
  1732								printf("}\n");
  1733							else if (!(test & TEST_PASS))
  1734								printf("-%d\n", state.lineno);
  1735						}
  1736					}
  1737#if defined(LC_COLLATE) && defined(LC_CTYPE)
  1738					else if (locale & level)
  1739					{
  1740						locale = 0;
  1741						if (!(skip & level))
  1742						{
  1743							s = "C";
  1744							setlocale(LC_COLLATE, s);
  1745							setlocale(LC_CTYPE, s);
  1746							if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
  1747								printf("NOTE	\"%s\" locale\n", s);
  1748							else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_PASS))
  1749								printf("}\n");
  1750						}
  1751						else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL))
  1752							printf("}\n");
  1753					}
  1754#endif
  1755					level >>= 1;
  1756					cflags = NOTEST;
  1757					continue;
  1758
  1759				default:
  1760					bad("bad spec\n", spec, NiL, 0, test);
  1761					break;
  1762
  1763				}
  1764				break;
  1765			}
  1766			if ((cflags|eflags) == NOTEST || (skip & level) && (test & TEST_BASELINE))
  1767			{
  1768				if (test & TEST_BASELINE)
  1769				{
  1770					while (i > 1)
  1771						*delim[--i] = '\t';
  1772					printf("%s\n", line);
  1773				}
  1774				continue;
  1775			}
  1776			if (test & TEST_OR)
  1777			{
  1778				if (!(test & TEST_VERIFY))
  1779				{
  1780					test &= ~TEST_OR;
  1781					if (state.passed == state.verify && i > 1)
  1782						printf("NOTE\t%s\n", field[1]);
  1783					continue;
  1784				}
  1785				else if (state.passed > state.verify)
  1786					continue;
  1787			}
  1788			else if (test & TEST_AND)
  1789			{
  1790				if (state.passed == state.verify)
  1791					continue;
  1792				state.passed = state.verify;
  1793			}
  1794			if (i < ((test & TEST_DECOMP) ? 3 : 4))
  1795				bad("too few fields\n", NiL, NiL, 0, test);
  1796			while (i < elementsof(field))
  1797				field[i++] = 0;
  1798			if (re = field[1])
  1799			{
  1800				if (streq(re, "SAME"))
  1801				{
  1802					re = ppat;
  1803					test |= TEST_SAME;
  1804				}
  1805				else
  1806				{
  1807					if (test & TEST_EXPAND)
  1808						escape(re);
  1809					re = expand(re, patbuf);
  1810					strcpy(ppat = pat, re);
  1811				}
  1812			}
  1813			else
  1814				ppat = 0;
  1815			nstr = -1;
  1816			if (s = field[2])
  1817			{
  1818				s = expand(s, strbuf);
  1819				if (test & TEST_EXPAND)
  1820				{
  1821					nstr = escape(s);
  1822#if _REG_nexec
  1823					if (nstr != strlen(s))
  1824						nexec = nstr;
  1825#endif
  1826				}
  1827			}
  1828			if (!(ans = field[(test & TEST_DECOMP) ? 2 : 3]))
  1829				bad("NIL answer\n", NiL, NiL, 0, test);
  1830			msg = field[4];
  1831			fflush(stdout);
  1832			if (test & TEST_SUB)
  1833#if _REG_subcomp
  1834				cflags |= REG_DELIMITED;
  1835#else
  1836				continue;
  1837#endif
  1838#if !_REG_decomp
  1839			if (test & TEST_DECOMP)
  1840				continue;
  1841#endif
  1842
  1843		compile:
  1844
  1845			if (state.extracted || (skip & level))
  1846				continue;
  1847#if !(REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL))
  1848#ifdef REG_EXTENDED
  1849			if (REG_EXTENDED != 0 && (test & TEST_BRE))
  1850#else
  1851			if (test & TEST_BRE)
  1852#endif
  1853			{
  1854				test &= ~TEST_BRE;
  1855				flags = cflags;
  1856				state.which = "BRE";
  1857			}
  1858			else
  1859#endif
  1860#ifdef REG_EXTENDED
  1861			if (test & TEST_ERE)
  1862			{
  1863				test &= ~TEST_ERE;
  1864				flags = cflags | REG_EXTENDED;
  1865				state.which = "ERE";
  1866			}
  1867			else
  1868#endif
  1869#ifdef REG_AUGMENTED
  1870			if (test & TEST_ARE)
  1871			{
  1872				test &= ~TEST_ARE;
  1873				flags = cflags | REG_AUGMENTED;
  1874				state.which = "ARE";
  1875			}
  1876			else
  1877#endif
  1878#ifdef REG_LITERAL
  1879			if (test & TEST_LRE)
  1880			{
  1881				test &= ~TEST_LRE;
  1882				flags = cflags | REG_LITERAL;
  1883				state.which = "LRE";
  1884			}
  1885			else
  1886#endif
  1887#ifdef REG_SHELL
  1888			if (test & TEST_SRE)
  1889			{
  1890				test &= ~TEST_SRE;
  1891				flags = cflags | REG_SHELL;
  1892				state.which = "SRE";
  1893			}
  1894			else
  1895#ifdef REG_AUGMENTED
  1896			if (test & TEST_KRE)
  1897			{
  1898				test &= ~TEST_KRE;
  1899				flags = cflags | REG_SHELL | REG_AUGMENTED;
  1900				state.which = "KRE";
  1901			}
  1902			else
  1903#endif
  1904#endif
  1905			{
  1906				if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY))
  1907					extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test|TEST_OK);
  1908				continue;
  1909			}
  1910			if ((test & (TEST_QUERY|TEST_VERBOSE|TEST_VERIFY)) == TEST_VERBOSE)
  1911			{
  1912				printf("test %-3d %s ", state.lineno, state.which);
  1913				quote(re, -1, test|TEST_DELIMIT);
  1914				printf(" ");
  1915				quote(s, nstr, test|TEST_DELIMIT);
  1916				printf("\n");
  1917			}
  1918
  1919		nosub:
  1920			fun = "regcomp";
  1921#if _REG_nexec
  1922			if (nstr >= 0 && nstr != strlen(s))
  1923				nexec = nstr;
  1924
  1925			else
  1926#endif
  1927				nexec = -1;
  1928			if (state.extracted || (skip & level))
  1929				continue;
  1930			if (!(test & TEST_QUERY))
  1931				testno++;
  1932#ifdef REG_DISCIPLINE
  1933			if (state.stack)
  1934				stkset(stkstd, state.stack, 0);
  1935			flags |= REG_DISCIPLINE;
  1936			state.disc.ordinal = 0;
  1937			sfstrseek(state.disc.sp, 0, SEEK_SET);
  1938#endif
  1939			if (!(test & TEST_CATCH))
  1940				cret = regcomp(&preg, re, flags);
  1941			else if (!(cret = setjmp(state.gotcha)))
  1942			{
  1943				alarm(HUNG);
  1944				cret = regcomp(&preg, re, flags);
  1945				alarm(0);
  1946			}
  1947#if _REG_subcomp
  1948			if (!cret && (test & TEST_SUB))
  1949			{
  1950				fun = "regsubcomp";
  1951				p = re + preg.re_npat;
  1952				if (!(test & TEST_CATCH))
  1953					cret = regsubcomp(&preg, p, NiL, 0, 0);
  1954				else if (!(cret = setjmp(state.gotcha)))
  1955				{
  1956					alarm(HUNG);
  1957					cret = regsubcomp(&preg, p, NiL, 0, 0);
  1958					alarm(0);
  1959				}
  1960				if (!cret && *(p += preg.re_npat) && !(preg.re_sub->re_flags & REG_SUB_LAST))
  1961				{
  1962					if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
  1963						continue;
  1964					cret = REG_EFLAGS;
  1965				}
  1966			}
  1967#endif
  1968#if _REG_decomp
  1969			if (!cret && (test & TEST_DECOMP))
  1970			{
  1971				char	buf[128];
  1972
  1973				if ((j = nmatch) > sizeof(buf))
  1974					j = sizeof(buf);
  1975				fun = "regdecomp";
  1976				p = re + preg.re_npat;
  1977				if (!(test & TEST_CATCH))
  1978					i = regdecomp(&preg, -1, buf, j);
  1979				else if (!(cret = setjmp(state.gotcha)))
  1980				{
  1981					alarm(HUNG);
  1982					i = regdecomp(&preg, -1, buf, j);
  1983					alarm(0);
  1984				}
  1985				if (!cret)
  1986				{
  1987					catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
  1988					if (i > j)
  1989					{
  1990						if (i != (strlen(ans) + 1))
  1991						{
  1992							report("failed", fun, re, s, nstr, msg, flags, test);
  1993							printf(" %d byte buffer supplied, %d byte buffer required\n", j, i);
  1994						}
  1995					}
  1996					else if (strcmp(buf, ans))
  1997					{
  1998						report("failed", fun, re, s, nstr, msg, flags, test);
  1999						quote(ans, -1, test|TEST_DELIMIT);
  2000						printf(" expected, ");
  2001						quote(buf, -1, test|TEST_DELIMIT);
  2002						printf(" returned\n");
  2003					}
  2004					continue;
  2005				}
  2006			}
  2007#endif
  2008			if (!cret)
  2009			{
  2010				if (!(flags & REG_NOSUB) && nsub < 0 && *ans == '(')
  2011				{
  2012					for (p = ans; *p; p++)
  2013						if (*p == '(')
  2014							nsub++;
  2015						else if (*p == '{')
  2016							nsub--;
  2017					if (nsub >= 0)
  2018					{
  2019						if (test & TEST_IGNORE_OVER)
  2020						{
  2021							if (nmatch > nsub)
  2022								nmatch = nsub + 1;
  2023						}
  2024						else if (nsub != preg.re_nsub)
  2025						{
  2026							if (nsub > preg.re_nsub)
  2027							{
  2028								if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2029									skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
  2030								else
  2031								{
  2032									report("re_nsub incorrect", fun, re, NiL, -1, msg, flags, test);
  2033									printf("at least %d expected, %d returned\n", nsub, preg.re_nsub);
  2034									state.errors++;
  2035								}
  2036							}
  2037							else
  2038								nsub = preg.re_nsub;
  2039						}
  2040					}
  2041				}
  2042				if (!(test & (TEST_DECOMP|TEST_SUB)) && *ans && *ans != '(' && !streq(ans, "OK") && !streq(ans, "NOMATCH"))
  2043				{
  2044					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2045						skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
  2046					else if (!(test & TEST_LENIENT))
  2047					{
  2048						report("failed", fun, re, NiL, -1, msg, flags, test);
  2049						printf("%s expected, OK returned\n", ans);
  2050					}
  2051					catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
  2052					continue;
  2053				}
  2054			}
  2055			else
  2056			{
  2057				if (test & TEST_LENIENT)
  2058					/* we'll let it go this time */;
  2059				else if (!*ans || ans[0]=='(' || cret == REG_BADPAT && streq(ans, "NOMATCH"))
  2060				{
  2061					got = 0;
  2062					for (i = 1; i < elementsof(codes); i++)
  2063						if (cret==codes[i].code)
  2064							got = i;
  2065					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2066						skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
  2067					else
  2068					{
  2069						report("failed", fun, re, NiL, -1, msg, flags, test);
  2070						printf("%s returned: ", codes[got].name);
  2071						error(&preg, cret);
  2072					}
  2073				}
  2074				else
  2075				{
  2076					expected = got = 0;
  2077					for (i = 1; i < elementsof(codes); i++)
  2078					{
  2079						if (streq(ans, codes[i].name))
  2080							expected = i;
  2081						if (cret==codes[i].code)
  2082							got = i;
  2083					}
  2084					if (!expected)
  2085					{
  2086						if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2087							skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
  2088						else
  2089						{
  2090							report("failed: invalid error code", NiL, re, NiL, -1, msg, flags, test);
  2091							printf("%s expected, %s returned\n", ans, codes[got].name);
  2092						}
  2093					}
  2094					else if (cret != codes[expected].code && cret != REG_BADPAT)
  2095					{
  2096						if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2097							skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
  2098						else if (test & TEST_IGNORE_ERROR)
  2099							state.ignored++;
  2100						else
  2101						{
  2102							report("should fail and did", fun, re, NiL, -1, msg, flags, test);
  2103							printf("%s expected, %s returned: ", ans, codes[got].name);
  2104							state.errors--;
  2105							state.warnings++;
  2106							error(&preg, cret);
  2107						}
  2108					}
  2109				}
  2110				goto compile;
  2111			}
  2112
  2113#if _REG_nexec
  2114		execute:
  2115			if (nexec >= 0)
  2116				fun = "regnexec";
  2117			else
  2118#endif
  2119				fun = "regexec";
  2120			
  2121			for (i = 0; i < elementsof(match); i++)
  2122				match[i] = state.NOMATCH;
  2123
  2124#if _REG_nexec
  2125			if (nexec >= 0)
  2126			{
  2127				eret = regnexec(&preg, s, nexec, nmatch, match, eflags);
  2128				s[nexec] = 0;
  2129			}
  2130			else
  2131#endif
  2132			{
  2133				if (!(test & TEST_CATCH))
  2134					eret = regexec(&preg, s, nmatch, match, eflags);
  2135				else if (!(eret = setjmp(state.gotcha)))
  2136				{
  2137					alarm(HUNG);
  2138					eret = regexec(&preg, s, nmatch, match, eflags);
  2139					alarm(0);
  2140				}
  2141			}
  2142#if _REG_subcomp
  2143			if ((test & TEST_SUB) && !eret)
  2144			{
  2145				fun = "regsubexec";
  2146				if (!(test & TEST_CATCH))
  2147					eret = regsubexec(&preg, s, nmatch, match);
  2148				else if (!(eret = setjmp(state.gotcha)))
  2149				{
  2150					alarm(HUNG);
  2151					eret = regsubexec(&preg, s, nmatch, match);
  2152					alarm(0);
  2153				}
  2154			}
  2155#endif
  2156			if (flags & REG_NOSUB)
  2157			{
  2158				if (eret)
  2159				{
  2160					if (eret != REG_NOMATCH || !streq(ans, "NOMATCH"))
  2161					{
  2162						if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2163							skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
  2164						else
  2165						{
  2166							report("REG_NOSUB failed", fun, re, s, nstr, msg, flags, test);
  2167							error(&preg, eret);
  2168						}
  2169					}
  2170				}
  2171				else if (streq(ans, "NOMATCH"))
  2172				{
  2173					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2174						skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
  2175					else
  2176					{
  2177						report("should fail and didn't", fun, re, s, nstr, msg, flags, test);
  2178						error(&preg, eret);
  2179					}
  2180				}
  2181			}
  2182			else if (eret)
  2183			{
  2184				if (eret != REG_NOMATCH || !streq(ans, "NOMATCH"))
  2185				{
  2186					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2187						skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, nsub, skip, level, test|TEST_DELIMIT);
  2188					else
  2189					{
  2190						report("failed", fun, re, s, nstr, msg, flags, test);
  2191						if (eret != REG_NOMATCH)
  2192							error(&preg, eret);
  2193						else if (*ans)
  2194							printf("expected: %s\n", ans);
  2195						else
  2196							printf("\n");
  2197					}
  2198				}
  2199			}
  2200			else if (streq(ans, "NOMATCH"))
  2201			{
  2202				if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2203					skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
  2204				else
  2205				{
  2206					report("should fail and didn't", fun, re, s, nstr, msg, flags, test);
  2207					matchprint(match, nmatch, nsub, NiL, test);
  2208				}
  2209			}
  2210#if _REG_subcomp
  2211			else if (test & TEST_SUB)
  2212			{
  2213				p = preg.re_sub->re_buf;
  2214				if (strcmp(p, ans))
  2215				{
  2216					report("failed", fun, re, s, nstr, msg, flags, test);
  2217					quote(ans, -1, test|TEST_DELIMIT);
  2218					printf(" expected, ");
  2219					quote(p, -1, test|TEST_DELIMIT);
  2220					printf(" returned\n");
  2221				}
  2222			}
  2223#endif
  2224			else if (!*ans)
  2225			{
  2226				if (match[0].rm_so != state.NOMATCH.rm_so)
  2227				{
  2228					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2229						skip = extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
  2230					else
  2231					{
  2232						report("failed: no match but match array assigned", NiL, re, s, nstr, msg, flags, test);
  2233						matchprint(match, nmatch, nsub, NiL, test);
  2234					}
  2235				}
  2236			}
  2237			else if (matchcheck(match, nmatch, nsub, ans, re, s, nstr, flags, test))
  2238			{
  2239#if _REG_nexec
  2240				if (nexec < 0 && !nonexec)
  2241				{
  2242					nexec = nstr >= 0 ? nstr : strlen(s);
  2243					s[nexec] = '\n';
  2244					testno++;
  2245					goto execute;
  2246				}
  2247#endif
  2248				if (!(test & (TEST_DECOMP|TEST_SUB|TEST_VERIFY)) && !nonosub)
  2249				{
  2250					if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
  2251						continue;
  2252					flags |= REG_NOSUB;
  2253					goto nosub;
  2254				}
  2255				if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY))
  2256					skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_OK);
  2257			}
  2258			else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
  2259				skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
  2260			if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
  2261				continue;
  2262			goto compile;
  2263		}
  2264		if (test & TEST_SUMMARY)
  2265			printf("tests=%-4d errors=%-4d warnings=%-2d ignored=%-2d unspecified=%-2d signals=%d\n", testno, state.errors, state.warnings, state.ignored, state.unspecified, state.signals);
  2266		else if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS)))
  2267		{
  2268			printf("TEST\t%s", unit);
  2269			if (subunit)
  2270				printf(" %-.*s", subunitlen, subunit);
  2271			printf(", %d test%s", testno, testno == 1 ? "" : "s");
  2272			if (state.ignored)
  2273				printf(", %d ignored mismatche%s", state.ignored, state.ignored == 1 ? "" : "s");
  2274			if (state.warnings)
  2275				printf(", %d warning%s", state.warnings, state.warnings == 1 ? "" : "s");
  2276			if (state.unspecified)
  2277				printf(", %d unspecified difference%s", state.unspecified, state.unspecified == 1 ? "" : "s");
  2278			if (state.signals)
  2279				printf(", %d signal%s", state.signals, state.signals == 1 ? "" : "s");
  2280			printf(", %d error%s\n", state.errors, state.errors == 1 ? "" : "s");
  2281		}
  2282		if (fp != stdin)
  2283			fclose(fp);
  2284	}
  2285	return 0;
  2286}

View as plain text