(root)/
gcc-13.2.0/
libgo/
go/
regexp/
testdata/
testregex.c
       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  }