Text file src/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  }
  2287  

View as plain text