Home | History | Annotate | Download | only in 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 (at) 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 (at) research.att.com        (ksh strmatch, regex extensions)\n");
    294 T("  David Korn      dgk (at) research.att.com        (ksh glob matcher)\n");
    295 T("  Doug McIlroy    mcilroy (at) dartmouth.edu       (ast regex/testre in C++)\n");
    296 T("  Tom Lord        lord (at) regexps.com            (rx tests)\n");
    297 T("  Henry Spencer   henry (at) zoo.toronto.edu       (original public regex)\n");
    298 T("  Andrew Hume     andrew (at) research.att.com     (gre tests)\n");
    299 T("  John Maddock    John_Maddock (at) compuserve.com (regex++ tests)\n");
    300 T("  Philip Hazel    ph10 (at) cam.ac.uk              (pcre tests)\n");
    301 T("  Ville Laurikari vl (at) 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 }
   2287