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