...
Run Format

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	
    37	static 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	
   113	typedef struct Disc_s
   114	{
   115		regdisc_t	disc;
   116		int		ordinal;
   117		Sfio_t*		sp;
   118	} Disc_t;
   119	
   120	static void*
   121	compf(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	
   128	static int
   129	execf(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	
   137	static void*
   138	resizef(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	
   158	static void
   159	help(int html)
   160	{
   161	H("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n");
   162	H("<HTML>\n");
   163	H("<HEAD>\n");
   164	H("<TITLE>testregex man document</TITLE>\n");
   165	H("</HEAD>\n");
   166	H("<BODY bgcolor=white>\n");
   167	H("<PRE>\n");
   168	T("NAME\n");
   169	T("  testregex - regex(3) test harness\n");
   170	T("\n");
   171	T("SYNOPSIS\n");
   172	T("  testregex [ options ]\n");
   173	T("\n");
   174	T("DESCRIPTION\n");
   175	T("  testregex reads regex(3) test specifications, one per line, from the\n");
   176	T("  standard input and writes one output line for each failed test. A\n");
   177	T("  summary line is written after all tests are done. Each successful\n");
   178	T("  test is run again with REG_NOSUB. Unsupported features are noted\n");
   179	T("  before the first test, and tests requiring these features are\n");
   180	T("  silently ignored.\n");
   181	T("\n");
   182	T("OPTIONS\n");
   183	T("  -c	catch signals and non-terminating calls\n");
   184	T("  -e	ignore error return mismatches\n");
   185	T("  -h	list help on standard error\n");
   186	T("  -n	do not repeat successful tests with regnexec()\n");
   187	T("  -o	ignore match[] overrun errors\n");
   188	T("  -p	ignore negative position mismatches\n");
   189	T("  -s	use stack instead of malloc\n");
   190	T("  -x	do not repeat successful tests with REG_NOSUB\n");
   191	T("  -v	list each test line\n");
   192	T("  -A	list failed test lines with actual answers\n");
   193	T("  -B	list all test lines with actual answers\n");
   194	T("  -F	list failed test lines\n");
   195	T("  -P	list passed test lines\n");
   196	T("  -S	output one summary line\n");
   197	T("\n");
   198	T("INPUT FORMAT\n");
   199	T("  Input lines may be blank, a comment beginning with #, or a test\n");
   200	T("  specification. A specification is five fields separated by one\n");
   201	T("  or more tabs. NULL denotes the empty string and NIL denotes the\n");
   202	T("  0 pointer.\n");
   203	T("\n");
   204	T("  Field 1: the regex(3) flags to apply, one character per REG_feature\n");
   205	T("  flag. The test is skipped if REG_feature is not supported by the\n");
   206	T("  implementation. If the first character is not [BEASKLP] then the\n");
   207	T("  specification is a global control line. One or more of [BEASKLP] may be\n");
   208	T("  specified; the test will be repeated for each mode.\n");
   209	T("\n");
   210	T("    B 	basic			BRE	(grep, ed, sed)\n");
   211	T("    E 	REG_EXTENDED		ERE	(egrep)\n");
   212	T("    A	REG_AUGMENTED		ARE	(egrep with negation)\n");
   213	T("    S	REG_SHELL		SRE	(sh glob)\n");
   214	T("    K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)\n");
   215	T("    L	REG_LITERAL		LRE	(fgrep)\n");
   216	T("\n");
   217	T("    a	REG_LEFT|REG_RIGHT	implicit ^...$\n");
   218	T("    b	REG_NOTBOL		lhs does not match ^\n");
   219	T("    c	REG_COMMENT		ignore space and #...\\n\n");
   220	T("    d	REG_SHELL_DOT		explicit leading . match\n");
   221	T("    e	REG_NOTEOL		rhs does not match $\n");
   222	T("    f	REG_MULTIPLE		multiple \\n separated patterns\n");
   223	T("    g	FNM_LEADING_DIR		testfnmatch only -- match until /\n");
   224	T("    h	REG_MULTIREF		multiple digit backref\n");
   225	T("    i	REG_ICASE		ignore case\n");
   226	T("    j	REG_SPAN		. matches \\n\n");
   227	T("    k	REG_ESCAPE		\\ to ecape [...] delimiter\n");
   228	T("    l	REG_LEFT		implicit ^...\n");
   229	T("    m	REG_MINIMAL		minimal match\n");
   230	T("    n	REG_NEWLINE		explicit \\n match\n");
   231	T("    o	REG_ENCLOSED		(|&) magic inside [@|&](...)\n");
   232	T("    p	REG_SHELL_PATH		explicit / match\n");
   233	T("    q	REG_DELIMITED		delimited pattern\n");
   234	T("    r	REG_RIGHT		implicit ...$\n");
   235	T("    s	REG_SHELL_ESCAPED	\\ not special\n");
   236	T("    t	REG_MUSTDELIM		all delimiters must be specified\n");
   237	T("    u	standard unspecified behavior -- errors not counted\n");
   238	T("    v	REG_CLASS_ESCAPE	\\ special inside [...]\n");
   239	T("    w	REG_NOSUB		no subexpression match array\n");
   240	T("    x	REG_LENIENT		let some errors slide\n");
   241	T("    y	REG_LEFT		regexec() implicit ^...\n");
   242	T("    z	REG_NULL		NULL subexpressions ok\n");
   243	T("    $	                        expand C \\c escapes in fields 2 and 3\n");
   244	T("    /	                        field 2 is a regsubcomp() expression\n");
   245	T("    =	                        field 3 is a regdecomp() expression\n");
   246	T("\n");
   247	T("  Field 1 control lines:\n");
   248	T("\n");
   249	T("    C		set LC_COLLATE and LC_CTYPE to locale in field 2\n");
   250	T("\n");
   251	T("    ?test ...	output field 5 if passed and != EXPECTED, silent otherwise\n");
   252	T("    &test ...	output field 5 if current and previous passed\n");
   253	T("    |test ...	output field 5 if current passed and previous failed\n");
   254	T("    ; ...	output field 2 if previous failed\n");
   255	T("    {test ...	skip if failed until }\n");
   256	T("    }		end of skip\n");
   257	T("\n");
   258	T("    : comment		comment copied as output NOTE\n");
   259	T("    :comment:test	:comment: ignored\n");
   260	T("    N[OTE] comment	comment copied as output NOTE\n");
   261	T("    T[EST] comment	comment\n");
   262	T("\n");
   263	T("    number		use number for nmatch (20 by default)\n");
   264	T("\n");
   265	T("  Field 2: the regular expression pattern; SAME uses the pattern from\n");
   266	T("    the previous specification. RE_DUP_MAX inside {...} expands to the\n");
   267	T("    value from <limits.h>.\n");
   268	T("\n");
   269	T("  Field 3: the string to match. X...{RE_DUP_MAX} expands to RE_DUP_MAX\n");
   270	T("    copies of X.\n");
   271	T("\n");
   272	T("  Field 4: the test outcome. This is either one of the posix error\n");
   273	T("    codes (with REG_ omitted) or the match array, a list of (m,n)\n");
   274	T("    entries with m and n being first and last+1 positions in the\n");
   275	T("    field 3 string, or NULL if REG_NOSUB is in effect and success\n");
   276	T("    is expected. BADPAT is acceptable in place of any regcomp(3)\n");
   277	T("    error code. The match[] array is initialized to (-2,-2) before\n");
   278	T("    each test. All array elements from 0 to nmatch-1 must be specified\n");
   279	T("    in the outcome. Unspecified endpoints (offset -1) are denoted by ?.\n");
   280	T("    Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a\n");
   281	T("    matched (?{...}) expression, where x is the text enclosed by {...},\n");
   282	T("    o is the expression ordinal counting from 1, and n is the length of\n");
   283	T("    the unmatched portion of the subject string. If x starts with a\n");
   284	T("    number then that is the return value of re_execf(), otherwise 0 is\n");
   285	T("    returned. RE_DUP_MAX[-+]N expands to the <limits.h> value -+N.\n");
   286	T("\n");
   287	T("  Field 5: optional comment appended to the report.\n");
   288	T("\n");
   289	T("CAVEAT\n");
   290	T("    If a regex implementation misbehaves with memory then all bets are off.\n");
   291	T("\n");
   292	T("CONTRIBUTORS\n");
   293	T("  Glenn Fowler    gsf@research.att.com        (ksh strmatch, regex extensions)\n");
   294	T("  David Korn      dgk@research.att.com        (ksh glob matcher)\n");
   295	T("  Doug McIlroy    mcilroy@dartmouth.edu       (ast regex/testre in C++)\n");
   296	T("  Tom Lord        lord@regexps.com            (rx tests)\n");
   297	T("  Henry Spencer   henry@zoo.toronto.edu       (original public regex)\n");
   298	T("  Andrew Hume     andrew@research.att.com     (gre tests)\n");
   299	T("  John Maddock    John_Maddock@compuserve.com (regex++ tests)\n");
   300	T("  Philip Hazel    ph10@cam.ac.uk              (pcre tests)\n");
   301	T("  Ville Laurikari vl@iki.fi                   (libtre tests)\n");
   302	H("</PRE>\n");
   303	H("</BODY>\n");
   304	H("</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	
   326	static 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	
   524	static 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	
   552	static 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	
   573	static void
   574	quote(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	
   653	static void
   654	report(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	
   692	static void
   693	error(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	
   716	static void
   717	bad(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	
   724	static int
   725	escape(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	
   840	static void
   841	matchoffprint(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	
   857	static void
   858	matchprint(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	
   881	static int
   882	matchcheck(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	
   989	static void
   990	sigunblock(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	
  1011	static void
  1012	gotcha(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	
  1035	static char*
  1036	getline(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	
  1060	static unsigned long
  1061	note(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	
  1075	static char		ts[] = "\t\t\t\t\t\t\t";
  1076	
  1077	static unsigned long
  1078	extract(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	
  1137	static int
  1138	catchfree(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	
  1163	static char*
  1164	expand(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	
  1216	int
  1217	main(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