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