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