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 <glenn.s.fowler@gmail.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 glenn.s.fowler@gmail.com (ksh strmatch, regex extensions)\n"); 294 T(" David Korn dgkorn@gmail.com (ksh glob matcher)\n"); 295 T(" Doug McIlroy mcilroy@dartmouth.edu (ast regex/testre in C++)\n"); 296 T(" Tom Lord lord@regexps.com (rx tests)\n"); 297 T(" Henry Spencer henry@zoo.toronto.edu (original public regex)\n"); 298 T(" Andrew Hume andrew@research.att.com (gre tests)\n"); 299 T(" John Maddock John_Maddock@compuserve.com (regex++ tests)\n"); 300 T(" Philip Hazel ph10@cam.ac.uk (pcre tests)\n"); 301 T(" Ville Laurikari vl@iki.fi (libtre tests)\n"); 302 H("</PRE>\n"); 303 H("</BODY>\n"); 304 H("</HTML>\n"); 305 } 306 307 #ifndef elementsof 308 #define elementsof(x) (sizeof(x)/sizeof(x[0])) 309 #endif 310 311 #ifndef streq 312 #define streq(a,b) (*(a)==*(b)&&!strcmp(a,b)) 313 #endif 314 315 #define HUNG 2 316 #define NOTEST (~0) 317 318 #ifndef REG_TEST_DEFAULT 319 #define REG_TEST_DEFAULT 0 320 #endif 321 322 #ifndef REG_EXEC_DEFAULT 323 #define REG_EXEC_DEFAULT 0 324 #endif 325 326 static const char* unsupported[] = 327 { 328 "BASIC", 329 #ifndef REG_EXTENDED 330 "EXTENDED", 331 #endif 332 #ifndef REG_AUGMENTED 333 "AUGMENTED", 334 #endif 335 #ifndef REG_SHELL 336 "SHELL", 337 #endif 338 339 #ifndef REG_CLASS_ESCAPE 340 "CLASS_ESCAPE", 341 #endif 342 #ifndef REG_COMMENT 343 "COMMENT", 344 #endif 345 #ifndef REG_DELIMITED 346 "DELIMITED", 347 #endif 348 #ifndef REG_DISCIPLINE 349 "DISCIPLINE", 350 #endif 351 #ifndef REG_ESCAPE 352 "ESCAPE", 353 #endif 354 #ifndef REG_ICASE 355 "ICASE", 356 #endif 357 #ifndef REG_LEFT 358 "LEFT", 359 #endif 360 #ifndef REG_LENIENT 361 "LENIENT", 362 #endif 363 #ifndef REG_LITERAL 364 "LITERAL", 365 #endif 366 #ifndef REG_MINIMAL 367 "MINIMAL", 368 #endif 369 #ifndef REG_MULTIPLE 370 "MULTIPLE", 371 #endif 372 #ifndef REG_MULTIREF 373 "MULTIREF", 374 #endif 375 #ifndef REG_MUSTDELIM 376 "MUSTDELIM", 377 #endif 378 #ifndef REG_NEWLINE 379 "NEWLINE", 380 #endif 381 #ifndef REG_NOTBOL 382 "NOTBOL", 383 #endif 384 #ifndef REG_NOTEOL 385 "NOTEOL", 386 #endif 387 #ifndef REG_NULL 388 "NULL", 389 #endif 390 #ifndef REG_RIGHT 391 "RIGHT", 392 #endif 393 #ifndef REG_SHELL_DOT 394 "SHELL_DOT", 395 #endif 396 #ifndef REG_SHELL_ESCAPED 397 "SHELL_ESCAPED", 398 #endif 399 #ifndef REG_SHELL_GROUP 400 "SHELL_GROUP", 401 #endif 402 #ifndef REG_SHELL_PATH 403 "SHELL_PATH", 404 #endif 405 #ifndef REG_SPAN 406 "SPAN", 407 #endif 408 #if REG_NOSUB & REG_TEST_DEFAULT 409 "SUBMATCH", 410 #endif 411 #if !_REG_nexec 412 "regnexec", 413 #endif 414 #if !_REG_subcomp 415 "regsubcomp", 416 #endif 417 #if !_REG_decomp 418 "redecomp", 419 #endif 420 0 421 }; 422 423 #ifndef REG_CLASS_ESCAPE 424 #define REG_CLASS_ESCAPE NOTEST 425 #endif 426 #ifndef REG_COMMENT 427 #define REG_COMMENT NOTEST 428 #endif 429 #ifndef REG_DELIMITED 430 #define REG_DELIMITED NOTEST 431 #endif 432 #ifndef REG_ESCAPE 433 #define REG_ESCAPE NOTEST 434 #endif 435 #ifndef REG_ICASE 436 #define REG_ICASE NOTEST 437 #endif 438 #ifndef REG_LEFT 439 #define REG_LEFT NOTEST 440 #endif 441 #ifndef REG_LENIENT 442 #define REG_LENIENT 0 443 #endif 444 #ifndef REG_MINIMAL 445 #define REG_MINIMAL NOTEST 446 #endif 447 #ifndef REG_MULTIPLE 448 #define REG_MULTIPLE NOTEST 449 #endif 450 #ifndef REG_MULTIREF 451 #define REG_MULTIREF NOTEST 452 #endif 453 #ifndef REG_MUSTDELIM 454 #define REG_MUSTDELIM NOTEST 455 #endif 456 #ifndef REG_NEWLINE 457 #define REG_NEWLINE NOTEST 458 #endif 459 #ifndef REG_NOTBOL 460 #define REG_NOTBOL NOTEST 461 #endif 462 #ifndef REG_NOTEOL 463 #define REG_NOTEOL NOTEST 464 #endif 465 #ifndef REG_NULL 466 #define REG_NULL NOTEST 467 #endif 468 #ifndef REG_RIGHT 469 #define REG_RIGHT NOTEST 470 #endif 471 #ifndef REG_SHELL_DOT 472 #define REG_SHELL_DOT NOTEST 473 #endif 474 #ifndef REG_SHELL_ESCAPED 475 #define REG_SHELL_ESCAPED NOTEST 476 #endif 477 #ifndef REG_SHELL_GROUP 478 #define REG_SHELL_GROUP NOTEST 479 #endif 480 #ifndef REG_SHELL_PATH 481 #define REG_SHELL_PATH NOTEST 482 #endif 483 #ifndef REG_SPAN 484 #define REG_SPAN NOTEST 485 #endif 486 487 #define REG_UNKNOWN (-1) 488 489 #ifndef REG_ENEWLINE 490 #define REG_ENEWLINE (REG_UNKNOWN-1) 491 #endif 492 #ifndef REG_ENULL 493 #ifndef REG_EMPTY 494 #define REG_ENULL (REG_UNKNOWN-2) 495 #else 496 #define REG_ENULL REG_EMPTY 497 #endif 498 #endif 499 #ifndef REG_ECOUNT 500 #define REG_ECOUNT (REG_UNKNOWN-3) 501 #endif 502 #ifndef REG_BADESC 503 #define REG_BADESC (REG_UNKNOWN-4) 504 #endif 505 #ifndef REG_EMEM 506 #define REG_EMEM (REG_UNKNOWN-5) 507 #endif 508 #ifndef REG_EHUNG 509 #define REG_EHUNG (REG_UNKNOWN-6) 510 #endif 511 #ifndef REG_EBUS 512 #define REG_EBUS (REG_UNKNOWN-7) 513 #endif 514 #ifndef REG_EFAULT 515 #define REG_EFAULT (REG_UNKNOWN-8) 516 #endif 517 #ifndef REG_EFLAGS 518 #define REG_EFLAGS (REG_UNKNOWN-9) 519 #endif 520 #ifndef REG_EDELIM 521 #define REG_EDELIM (REG_UNKNOWN-9) 522 #endif 523 524 static const struct { int code; char* name; } codes[] = 525 { 526 REG_UNKNOWN, "UNKNOWN", 527 REG_NOMATCH, "NOMATCH", 528 REG_BADPAT, "BADPAT", 529 REG_ECOLLATE, "ECOLLATE", 530 REG_ECTYPE, "ECTYPE", 531 REG_EESCAPE, "EESCAPE", 532 REG_ESUBREG, "ESUBREG", 533 REG_EBRACK, "EBRACK", 534 REG_EPAREN, "EPAREN", 535 REG_EBRACE, "EBRACE", 536 REG_BADBR, "BADBR", 537 REG_ERANGE, "ERANGE", 538 REG_ESPACE, "ESPACE", 539 REG_BADRPT, "BADRPT", 540 REG_ENEWLINE, "ENEWLINE", 541 REG_ENULL, "ENULL", 542 REG_ECOUNT, "ECOUNT", 543 REG_BADESC, "BADESC", 544 REG_EMEM, "EMEM", 545 REG_EHUNG, "EHUNG", 546 REG_EBUS, "EBUS", 547 REG_EFAULT, "EFAULT", 548 REG_EFLAGS, "EFLAGS", 549 REG_EDELIM, "EDELIM", 550 }; 551 552 static struct 553 { 554 regmatch_t NOMATCH; 555 int errors; 556 int extracted; 557 int ignored; 558 int lineno; 559 int passed; 560 int signals; 561 int unspecified; 562 int verify; 563 int warnings; 564 char* file; 565 char* stack; 566 char* which; 567 jmp_buf gotcha; 568 #ifdef REG_DISCIPLINE 569 Disc_t disc; 570 #endif 571 } state; 572 573 static void 574 quote(char* s, int len, unsigned long test) 575 { 576 unsigned char* u = (unsigned char*)s; 577 unsigned char* e; 578 int c; 579 #ifdef MB_CUR_MAX 580 int w; 581 #endif 582 583 if (!u) 584 printf("NIL"); 585 else if (!*u && len <= 1) 586 printf("NULL"); 587 else if (test & TEST_EXPAND) 588 { 589 if (len < 0) 590 len = strlen((char*)u); 591 e = u + len; 592 if (test & TEST_DELIMIT) 593 printf("\""); 594 while (u < e) 595 switch (c = *u++) 596 { 597 case '\\': 598 printf("\\\\"); 599 break; 600 case '"': 601 if (test & TEST_DELIMIT) 602 printf("\\\""); 603 else 604 printf("\""); 605 break; 606 case '\a': 607 printf("\\a"); 608 break; 609 case '\b': 610 printf("\\b"); 611 break; 612 case 033: 613 printf("\\e"); 614 break; 615 case '\f': 616 printf("\\f"); 617 break; 618 case '\n': 619 printf("\\n"); 620 break; 621 case '\r': 622 printf("\\r"); 623 break; 624 case '\t': 625 printf("\\t"); 626 break; 627 case '\v': 628 printf("\\v"); 629 break; 630 default: 631 #ifdef MB_CUR_MAX 632 s = (char*)u - 1; 633 if ((w = mblen(s, (char*)e - s)) > 1) 634 { 635 u += w - 1; 636 fwrite(s, 1, w, stdout); 637 } 638 else 639 #endif 640 if (!iscntrl(c) && isprint(c)) 641 putchar(c); 642 else 643 printf("\\x%02x", c); 644 break; 645 } 646 if (test & TEST_DELIMIT) 647 printf("\""); 648 } 649 else 650 printf("%s", s); 651 } 652 653 static void 654 report(char* comment, char* fun, char* re, char* s, int len, char* msg, int flags, unsigned long test) 655 { 656 if (state.file) 657 printf("%s:", state.file); 658 printf("%d:", state.lineno); 659 if (re) 660 { 661 printf(" "); 662 quote(re, -1, test|TEST_DELIMIT); 663 if (s) 664 { 665 printf(" versus "); 666 quote(s, len, test|TEST_DELIMIT); 667 } 668 } 669 if (test & TEST_UNSPECIFIED) 670 { 671 state.unspecified++; 672 printf(" unspecified behavior"); 673 } 674 else 675 state.errors++; 676 if (state.which) 677 printf(" %s", state.which); 678 if (flags & REG_NOSUB) 679 printf(" NOSUB"); 680 if (fun) 681 printf(" %s", fun); 682 if (comment[strlen(comment)-1] == '\n') 683 printf(" %s", comment); 684 else 685 { 686 printf(" %s: ", comment); 687 if (msg) 688 printf("%s: ", msg); 689 } 690 } 691 692 static void 693 error(regex_t* preg, int code) 694 { 695 char* msg; 696 char buf[256]; 697 698 switch (code) 699 { 700 case REG_EBUS: 701 msg = "bus error"; 702 break; 703 case REG_EFAULT: 704 msg = "memory fault"; 705 break; 706 case REG_EHUNG: 707 msg = "did not terminate"; 708 break; 709 default: 710 regerror(code, preg, msg = buf, sizeof buf); 711 break; 712 } 713 printf("%s\n", msg); 714 } 715 716 static void 717 bad(char* comment, char* re, char* s, int len, unsigned long test) 718 { 719 printf("bad test case "); 720 report(comment, NiL, re, s, len, NiL, 0, test); 721 exit(1); 722 } 723 724 static int 725 escape(char* s) 726 { 727 char* b; 728 char* t; 729 char* q; 730 char* e; 731 int c; 732 733 for (b = t = s; *t = *s; s++, t++) 734 if (*s == '\\') 735 switch (*++s) 736 { 737 case '\\': 738 break; 739 case 'a': 740 *t = '\a'; 741 break; 742 case 'b': 743 *t = '\b'; 744 break; 745 case 'c': 746 if (*t = *++s) 747 *t &= 037; 748 else 749 s--; 750 break; 751 case 'e': 752 case 'E': 753 *t = 033; 754 break; 755 case 'f': 756 *t = '\f'; 757 break; 758 case 'n': 759 *t = '\n'; 760 break; 761 case 'r': 762 *t = '\r'; 763 break; 764 case 's': 765 *t = ' '; 766 break; 767 case 't': 768 *t = '\t'; 769 break; 770 case 'v': 771 *t = '\v'; 772 break; 773 case 'u': 774 case 'x': 775 c = 0; 776 q = c == 'u' ? (s + 5) : (char*)0; 777 e = s + 1; 778 while (!e || !q || s < q) 779 { 780 switch (*++s) 781 { 782 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 783 c = (c << 4) + *s - 'a' + 10; 784 continue; 785 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 786 c = (c << 4) + *s - 'A' + 10; 787 continue; 788 case '0': case '1': case '2': case '3': case '4': 789 case '5': case '6': case '7': case '8': case '9': 790 c = (c << 4) + *s - '0'; 791 continue; 792 case '{': 793 case '[': 794 if (s != e) 795 { 796 s--; 797 break; 798 } 799 e = 0; 800 continue; 801 case '}': 802 case ']': 803 if (e) 804 s--; 805 break; 806 default: 807 s--; 808 break; 809 } 810 break; 811 } 812 *t = c; 813 break; 814 case '0': case '1': case '2': case '3': 815 case '4': case '5': case '6': case '7': 816 c = *s - '0'; 817 q = s + 2; 818 while (s < q) 819 { 820 switch (*++s) 821 { 822 case '0': case '1': case '2': case '3': 823 case '4': case '5': case '6': case '7': 824 c = (c << 3) + *s - '0'; 825 break; 826 default: 827 q = --s; 828 break; 829 } 830 } 831 *t = c; 832 break; 833 default: 834 *(s + 1) = 0; 835 bad("invalid C \\ escape\n", s - 1, NiL, 0, 0); 836 } 837 return t - b; 838 } 839 840 static void 841 matchoffprint(int off) 842 { 843 switch (off) 844 { 845 case -2: 846 printf("X"); 847 break; 848 case -1: 849 printf("?"); 850 break; 851 default: 852 printf("%d", off); 853 break; 854 } 855 } 856 857 static void 858 matchprint(regmatch_t* match, int nmatch, int nsub, char* ans, unsigned long test) 859 { 860 int i; 861 862 for (; nmatch > nsub + 1; nmatch--) 863 if ((match[nmatch-1].rm_so != -1 || match[nmatch-1].rm_eo != -1) && (!(test & TEST_IGNORE_POSITION) || match[nmatch-1].rm_so >= 0 && match[nmatch-1].rm_eo >= 0)) 864 break; 865 for (i = 0; i < nmatch; i++) 866 { 867 printf("("); 868 matchoffprint(match[i].rm_so); 869 printf(","); 870 matchoffprint(match[i].rm_eo); 871 printf(")"); 872 } 873 if (!(test & (TEST_ACTUAL|TEST_BASELINE))) 874 { 875 if (ans) 876 printf(" expected: %s", ans); 877 printf("\n"); 878 } 879 } 880 881 static int 882 matchcheck(regmatch_t* match, int nmatch, int nsub, char* ans, char* re, char* s, int len, int flags, unsigned long test) 883 { 884 char* p; 885 int i; 886 int m; 887 int n; 888 889 if (streq(ans, "OK")) 890 return test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY); 891 for (i = 0, p = ans; i < nmatch && *p; i++) 892 { 893 if (*p == '{') 894 { 895 #ifdef REG_DISCIPLINE 896 char* x; 897 898 if (!(x = sfstruse(state.disc.sp))) 899 bad("out of space [discipline string]\n", NiL, NiL, 0, 0); 900 if (strcmp(p, x)) 901 { 902 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 903 return 0; 904 report("callout failed", NiL, re, s, len, NiL, flags, test); 905 quote(p, -1, test); 906 printf(" expected, "); 907 quote(x, -1, test); 908 printf(" returned\n"); 909 } 910 #endif 911 break; 912 } 913 if (*p++ != '(') 914 bad("improper answer\n", re, s, -1, test); 915 if (*p == '?') 916 { 917 m = -1; 918 p++; 919 } 920 else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10)) 921 { 922 m = RE_DUP_MAX; 923 p += 10; 924 if (*p == '+' || *p == '-') 925 m += strtol(p, &p, 10); 926 } 927 else 928 m = strtol(p, &p, 10); 929 if (*p++ != ',') 930 bad("improper answer\n", re, s, -1, test); 931 if (*p == '?') 932 { 933 n = -1; 934 p++; 935 } 936 else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10)) 937 { 938 n = RE_DUP_MAX; 939 p += 10; 940 if (*p == '+' || *p == '-') 941 n += strtol(p, &p, 10); 942 } 943 else 944 n = strtol(p, &p, 10); 945 if (*p++ != ')') 946 bad("improper answer\n", re, s, -1, test); 947 if (m!=match[i].rm_so || n!=match[i].rm_eo) 948 { 949 if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))) 950 { 951 report("failed: match was", NiL, re, s, len, NiL, flags, test); 952 matchprint(match, nmatch, nsub, ans, test); 953 } 954 return 0; 955 } 956 } 957 for (; i < nmatch; i++) 958 { 959 if (match[i].rm_so!=-1 || match[i].rm_eo!=-1) 960 { 961 if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_VERIFY))) 962 { 963 if ((test & TEST_IGNORE_POSITION) && (match[i].rm_so<0 || match[i].rm_eo<0)) 964 { 965 state.ignored++; 966 return 0; 967 } 968 if (!(test & TEST_SUMMARY)) 969 { 970 report("failed: match was", NiL, re, s, len, NiL, flags, test); 971 matchprint(match, nmatch, nsub, ans, test); 972 } 973 } 974 return 0; 975 } 976 } 977 if (!(test & TEST_IGNORE_OVER) && match[nmatch].rm_so != state.NOMATCH.rm_so) 978 { 979 if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))) 980 { 981 report("failed: overran match array", NiL, re, s, len, NiL, flags, test); 982 matchprint(match, nmatch + 1, nsub, NiL, test); 983 } 984 return 0; 985 } 986 return 1; 987 } 988 989 static void 990 sigunblock(int s) 991 { 992 #ifdef SIG_SETMASK 993 int op; 994 sigset_t mask; 995 996 sigemptyset(&mask); 997 if (s) 998 { 999 sigaddset(&mask, s); 1000 op = SIG_UNBLOCK; 1001 } 1002 else op = SIG_SETMASK; 1003 sigprocmask(op, &mask, NiL); 1004 #else 1005 #ifdef sigmask 1006 sigsetmask(s ? (sigsetmask(0L) & ~sigmask(s)) : 0L); 1007 #endif 1008 #endif 1009 } 1010 1011 static void 1012 gotcha(int sig) 1013 { 1014 int ret; 1015 1016 signal(sig, gotcha); 1017 alarm(0); 1018 state.signals++; 1019 switch (sig) 1020 { 1021 case SIGALRM: 1022 ret = REG_EHUNG; 1023 break; 1024 case SIGBUS: 1025 ret = REG_EBUS; 1026 break; 1027 default: 1028 ret = REG_EFAULT; 1029 break; 1030 } 1031 sigunblock(sig); 1032 longjmp(state.gotcha, ret); 1033 } 1034 1035 static char* 1036 get_line(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 #if _REG_nexec 1224 int nexec; 1225 #endif 1226 int nstr; 1227 int cret; 1228 int eret; 1229 int nsub; 1230 int i; 1231 int j; 1232 int expected; 1233 int got; 1234 int locale; 1235 int subunitlen; 1236 int testno; 1237 unsigned long level; 1238 unsigned long skip; 1239 char* p; 1240 char* line; 1241 char* spec; 1242 char* re; 1243 char* s; 1244 char* ans; 1245 char* msg; 1246 char* fun; 1247 char* ppat; 1248 char* subunit; 1249 char* version; 1250 char* field[6]; 1251 char* delim[6]; 1252 FILE* fp; 1253 int tabs[6]; 1254 char unit[64]; 1255 regmatch_t match[100]; 1256 regex_t preg; 1257 1258 static char pat[32 * 1024]; 1259 static char patbuf[32 * 1024]; 1260 static char strbuf[32 * 1024]; 1261 1262 int nonosub = REG_NOSUB == 0; 1263 #if _REG_nexec 1264 int nonexec = 0; 1265 #endif 1266 1267 unsigned long test = 0; 1268 1269 static char* filter[] = { "-", 0 }; 1270 1271 state.NOMATCH.rm_so = state.NOMATCH.rm_eo = -2; 1272 p = unit; 1273 version = (char*)id + 10; 1274 while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace(*p)) 1275 p++; 1276 *p = 0; 1277 while ((p = *++argv) && *p == '-') 1278 for (;;) 1279 { 1280 switch (*++p) 1281 { 1282 case 0: 1283 break; 1284 case 'c': 1285 test |= TEST_CATCH; 1286 continue; 1287 case 'e': 1288 test |= TEST_IGNORE_ERROR; 1289 continue; 1290 case 'h': 1291 case '?': 1292 help(0); 1293 return 2; 1294 case '-': 1295 help(p[1] == 'h'); 1296 return 2; 1297 case 'n': 1298 #if _REG_nexec 1299 nonexec = 1; 1300 #endif 1301 continue; 1302 case 'o': 1303 test |= TEST_IGNORE_OVER; 1304 continue; 1305 case 'p': 1306 test |= TEST_IGNORE_POSITION; 1307 continue; 1308 case 's': 1309 #ifdef REG_DISCIPLINE 1310 if (!(state.stack = stkalloc(stkstd, 0))) 1311 fprintf(stderr, "%s: out of space [stack]", unit); 1312 state.disc.disc.re_resizef = resizef; 1313 state.disc.disc.re_resizehandle = (void*)stkstd; 1314 #endif 1315 continue; 1316 case 'x': 1317 nonosub = 1; 1318 continue; 1319 case 'v': 1320 test |= TEST_VERBOSE; 1321 continue; 1322 case 'A': 1323 test |= TEST_ACTUAL; 1324 continue; 1325 case 'B': 1326 test |= TEST_BASELINE; 1327 continue; 1328 case 'F': 1329 test |= TEST_FAIL; 1330 continue; 1331 case 'P': 1332 test |= TEST_PASS; 1333 continue; 1334 case 'S': 1335 test |= TEST_SUMMARY; 1336 continue; 1337 default: 1338 fprintf(stderr, "%s: %c: invalid option\n", unit, *p); 1339 return 2; 1340 } 1341 break; 1342 } 1343 if (!*argv) 1344 argv = filter; 1345 locale = 0; 1346 while (state.file = *argv++) 1347 { 1348 if (streq(state.file, "-") || streq(state.file, "/dev/stdin") || streq(state.file, "/dev/fd/0")) 1349 { 1350 state.file = 0; 1351 fp = stdin; 1352 } 1353 else if (!(fp = fopen(state.file, "r"))) 1354 { 1355 fprintf(stderr, "%s: %s: cannot read\n", unit, state.file); 1356 return 2; 1357 } 1358 testno = state.errors = state.ignored = state.lineno = state.passed = 1359 state.signals = state.unspecified = state.warnings = 0; 1360 skip = 0; 1361 level = 1; 1362 if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) 1363 { 1364 printf("TEST\t%s ", unit); 1365 if (s = state.file) 1366 { 1367 subunit = p = 0; 1368 for (;;) 1369 { 1370 switch (*s++) 1371 { 1372 case 0: 1373 break; 1374 case '/': 1375 subunit = s; 1376 continue; 1377 case '.': 1378 p = s - 1; 1379 continue; 1380 default: 1381 continue; 1382 } 1383 break; 1384 } 1385 if (!subunit) 1386 subunit = state.file; 1387 if (p < subunit) 1388 p = s - 1; 1389 subunitlen = p - subunit; 1390 printf("%-.*s ", subunitlen, subunit); 1391 } 1392 else 1393 subunit = 0; 1394 for (s = version; *s && (*s != ' ' || *(s + 1) != '$'); s++) 1395 putchar(*s); 1396 if (test & TEST_CATCH) 1397 printf(", catch"); 1398 if (test & TEST_IGNORE_ERROR) 1399 printf(", ignore error code mismatches"); 1400 if (test & TEST_IGNORE_POSITION) 1401 printf(", ignore negative position mismatches"); 1402 #ifdef REG_DISCIPLINE 1403 if (state.stack) 1404 printf(", stack"); 1405 #endif 1406 if (test & TEST_VERBOSE) 1407 printf(", verbose"); 1408 printf("\n"); 1409 #ifdef REG_VERSIONID 1410 if (regerror(REG_VERSIONID, NiL, pat, sizeof(pat)) > 0) 1411 s = pat; 1412 else 1413 #endif 1414 #ifdef REG_TEST_VERSION 1415 s = REG_TEST_VERSION; 1416 #else 1417 s = "regex"; 1418 #endif 1419 printf("NOTE\t%s\n", s); 1420 if (elementsof(unsupported) > 1) 1421 { 1422 #if (REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) || !defined(REG_EXTENDED) 1423 i = 0; 1424 #else 1425 i = REG_EXTENDED != 0; 1426 #endif 1427 for (got = 0; i < elementsof(unsupported) - 1; i++) 1428 { 1429 if (!got) 1430 { 1431 got = 1; 1432 printf("NOTE\tunsupported: %s", unsupported[i]); 1433 } 1434 else 1435 printf(",%s", unsupported[i]); 1436 } 1437 if (got) 1438 printf("\n"); 1439 } 1440 } 1441 #ifdef REG_DISCIPLINE 1442 state.disc.disc.re_version = REG_VERSION; 1443 state.disc.disc.re_compf = compf; 1444 state.disc.disc.re_execf = execf; 1445 if (!(state.disc.sp = sfstropen())) 1446 bad("out of space [discipline string stream]\n", NiL, NiL, 0, 0); 1447 preg.re_disc = &state.disc.disc; 1448 #endif 1449 if (test & TEST_CATCH) 1450 { 1451 signal(SIGALRM, gotcha); 1452 signal(SIGBUS, gotcha); 1453 signal(SIGSEGV, gotcha); 1454 } 1455 while (p = get_line(fp)) 1456 { 1457 1458 /* parse: */ 1459 1460 line = p; 1461 if (*p == ':' && !isspace(*(p + 1))) 1462 { 1463 while (*++p && *p != ':'); 1464 if (!*p++) 1465 { 1466 if (test & TEST_BASELINE) 1467 printf("%s\n", line); 1468 continue; 1469 } 1470 } 1471 while (isspace(*p)) 1472 p++; 1473 if (*p == 0 || *p == '#' || *p == 'T') 1474 { 1475 if (test & TEST_BASELINE) 1476 printf("%s\n", line); 1477 continue; 1478 } 1479 if (*p == ':' || *p == 'N') 1480 { 1481 if (test & TEST_BASELINE) 1482 printf("%s\n", line); 1483 else if (!(test & (TEST_ACTUAL|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) 1484 { 1485 while (*++p && !isspace(*p)); 1486 while (isspace(*p)) 1487 p++; 1488 printf("NOTE %s\n", p); 1489 } 1490 continue; 1491 } 1492 j = 0; 1493 i = 0; 1494 field[i++] = p; 1495 for (;;) 1496 { 1497 switch (*p++) 1498 { 1499 case 0: 1500 p--; 1501 j = 0; 1502 goto checkfield; 1503 case '\t': 1504 *(delim[i] = p - 1) = 0; 1505 j = 1; 1506 checkfield: 1507 s = field[i - 1]; 1508 if (streq(s, "NIL")) 1509 field[i - 1] = 0; 1510 else if (streq(s, "NULL")) 1511 *s = 0; 1512 while (*p == '\t') 1513 { 1514 p++; 1515 j++; 1516 } 1517 tabs[i - 1] = j; 1518 if (!*p) 1519 break; 1520 if (i >= elementsof(field)) 1521 bad("too many fields\n", NiL, NiL, 0, 0); 1522 field[i++] = p; 1523 /*FALLTHROUGH*/ 1524 default: 1525 continue; 1526 } 1527 break; 1528 } 1529 if (!(spec = field[0])) 1530 bad("NIL spec\n", NiL, NiL, 0, 0); 1531 1532 /* interpret: */ 1533 1534 cflags = REG_TEST_DEFAULT; 1535 eflags = REG_EXEC_DEFAULT; 1536 test &= TEST_GLOBAL; 1537 state.extracted = 0; 1538 nmatch = 20; 1539 nsub = -1; 1540 for (p = spec; *p; p++) 1541 { 1542 if (isdigit(*p)) 1543 { 1544 nmatch = strtol(p, &p, 10); 1545 if (nmatch >= elementsof(match)) 1546 bad("nmatch must be < 100\n", NiL, NiL, 0, 0); 1547 p--; 1548 continue; 1549 } 1550 switch (*p) 1551 { 1552 case 'A': 1553 test |= TEST_ARE; 1554 continue; 1555 case 'B': 1556 test |= TEST_BRE; 1557 continue; 1558 case 'C': 1559 if (!(test & TEST_QUERY) && !(skip & level)) 1560 bad("locale must be nested\n", NiL, NiL, 0, 0); 1561 test &= ~TEST_QUERY; 1562 if (locale) 1563 bad("locale nesting not supported\n", NiL, NiL, 0, 0); 1564 if (i != 2) 1565 bad("locale field expected\n", NiL, NiL, 0, 0); 1566 if (!(skip & level)) 1567 { 1568 #if defined(LC_COLLATE) && defined(LC_CTYPE) 1569 s = field[1]; 1570 if (!s || streq(s, "POSIX")) 1571 s = "C"; 1572 if ((ans = setlocale(LC_COLLATE, s)) && streq(ans, "POSIX")) 1573 ans = "C"; 1574 if (!ans || !streq(ans, s) && streq(s, "C")) 1575 ans = 0; 1576 else if ((ans = setlocale(LC_CTYPE, s)) && streq(ans, "POSIX")) 1577 ans = "C"; 1578 if (!ans || !streq(ans, s) && streq(s, "C")) 1579 skip = note(level, s, skip, test); 1580 else 1581 { 1582 if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) 1583 printf("NOTE \"%s\" locale\n", s); 1584 locale = level; 1585 } 1586 #else 1587 skip = note(level, skip, test, "locales not supported"); 1588 #endif 1589 } 1590 cflags = NOTEST; 1591 continue; 1592 case 'E': 1593 test |= TEST_ERE; 1594 continue; 1595 case 'K': 1596 test |= TEST_KRE; 1597 continue; 1598 case 'L': 1599 test |= TEST_LRE; 1600 continue; 1601 case 'S': 1602 test |= TEST_SRE; 1603 continue; 1604 1605 case 'a': 1606 cflags |= REG_LEFT|REG_RIGHT; 1607 continue; 1608 case 'b': 1609 eflags |= REG_NOTBOL; 1610 continue; 1611 case 'c': 1612 cflags |= REG_COMMENT; 1613 continue; 1614 case 'd': 1615 cflags |= REG_SHELL_DOT; 1616 continue; 1617 case 'e': 1618 eflags |= REG_NOTEOL; 1619 continue; 1620 case 'f': 1621 cflags |= REG_MULTIPLE; 1622 continue; 1623 case 'g': 1624 cflags |= NOTEST; 1625 continue; 1626 case 'h': 1627 cflags |= REG_MULTIREF; 1628 continue; 1629 case 'i': 1630 cflags |= REG_ICASE; 1631 continue; 1632 case 'j': 1633 cflags |= REG_SPAN; 1634 continue; 1635 case 'k': 1636 cflags |= REG_ESCAPE; 1637 continue; 1638 case 'l': 1639 cflags |= REG_LEFT; 1640 continue; 1641 case 'm': 1642 cflags |= REG_MINIMAL; 1643 continue; 1644 case 'n': 1645 cflags |= REG_NEWLINE; 1646 continue; 1647 case 'o': 1648 cflags |= REG_SHELL_GROUP; 1649 continue; 1650 case 'p': 1651 cflags |= REG_SHELL_PATH; 1652 continue; 1653 case 'q': 1654 cflags |= REG_DELIMITED; 1655 continue; 1656 case 'r': 1657 cflags |= REG_RIGHT; 1658 continue; 1659 case 's': 1660 cflags |= REG_SHELL_ESCAPED; 1661 continue; 1662 case 't': 1663 cflags |= REG_MUSTDELIM; 1664 continue; 1665 case 'u': 1666 test |= TEST_UNSPECIFIED; 1667 continue; 1668 case 'v': 1669 cflags |= REG_CLASS_ESCAPE; 1670 continue; 1671 case 'w': 1672 cflags |= REG_NOSUB; 1673 continue; 1674 case 'x': 1675 if (REG_LENIENT) 1676 cflags |= REG_LENIENT; 1677 else 1678 test |= TEST_LENIENT; 1679 continue; 1680 case 'y': 1681 eflags |= REG_LEFT; 1682 continue; 1683 case 'z': 1684 cflags |= REG_NULL; 1685 continue; 1686 1687 case '$': 1688 test |= TEST_EXPAND; 1689 continue; 1690 1691 case '/': 1692 test |= TEST_SUB; 1693 continue; 1694 1695 case '=': 1696 test |= TEST_DECOMP; 1697 continue; 1698 1699 case '?': 1700 test |= TEST_VERIFY; 1701 test &= ~(TEST_AND|TEST_OR); 1702 state.verify = state.passed; 1703 continue; 1704 case '&': 1705 test |= TEST_VERIFY|TEST_AND; 1706 test &= ~TEST_OR; 1707 continue; 1708 case '|': 1709 test |= TEST_VERIFY|TEST_OR; 1710 test &= ~TEST_AND; 1711 continue; 1712 case ';': 1713 test |= TEST_OR; 1714 test &= ~TEST_AND; 1715 continue; 1716 1717 case '{': 1718 level <<= 1; 1719 if (skip & (level >> 1)) 1720 { 1721 skip |= level; 1722 cflags = NOTEST; 1723 } 1724 else 1725 { 1726 skip &= ~level; 1727 test |= TEST_QUERY; 1728 } 1729 continue; 1730 case '}': 1731 if (level == 1) 1732 bad("invalid {...} nesting\n", NiL, NiL, 0, 0); 1733 if ((skip & level) && !(skip & (level>>1))) 1734 { 1735 if (!(test & (TEST_BASELINE|TEST_SUMMARY))) 1736 { 1737 if (test & (TEST_ACTUAL|TEST_FAIL)) 1738 printf("}\n"); 1739 else if (!(test & TEST_PASS)) 1740 printf("-%d\n", state.lineno); 1741 } 1742 } 1743 #if defined(LC_COLLATE) && defined(LC_CTYPE) 1744 else if (locale & level) 1745 { 1746 locale = 0; 1747 if (!(skip & level)) 1748 { 1749 s = "C"; 1750 setlocale(LC_COLLATE, s); 1751 setlocale(LC_CTYPE, s); 1752 if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) 1753 printf("NOTE \"%s\" locale\n", s); 1754 else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_PASS)) 1755 printf("}\n"); 1756 } 1757 else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL)) 1758 printf("}\n"); 1759 } 1760 #endif 1761 level >>= 1; 1762 cflags = NOTEST; 1763 continue; 1764 1765 default: 1766 bad("bad spec\n", spec, NiL, 0, test); 1767 break; 1768 1769 } 1770 break; 1771 } 1772 if ((cflags|eflags) == NOTEST || (skip & level) && (test & TEST_BASELINE)) 1773 { 1774 if (test & TEST_BASELINE) 1775 { 1776 while (i > 1) 1777 *delim[--i] = '\t'; 1778 printf("%s\n", line); 1779 } 1780 continue; 1781 } 1782 if (test & TEST_OR) 1783 { 1784 if (!(test & TEST_VERIFY)) 1785 { 1786 test &= ~TEST_OR; 1787 if (state.passed == state.verify && i > 1) 1788 printf("NOTE\t%s\n", field[1]); 1789 continue; 1790 } 1791 else if (state.passed > state.verify) 1792 continue; 1793 } 1794 else if (test & TEST_AND) 1795 { 1796 if (state.passed == state.verify) 1797 continue; 1798 state.passed = state.verify; 1799 } 1800 if (i < ((test & TEST_DECOMP) ? 3 : 4)) 1801 bad("too few fields\n", NiL, NiL, 0, test); 1802 while (i < elementsof(field)) 1803 field[i++] = 0; 1804 if (re = field[1]) 1805 { 1806 if (streq(re, "SAME")) 1807 { 1808 re = ppat; 1809 test |= TEST_SAME; 1810 } 1811 else 1812 { 1813 if (test & TEST_EXPAND) 1814 escape(re); 1815 re = expand(re, patbuf); 1816 strcpy(ppat = pat, re); 1817 } 1818 } 1819 else 1820 ppat = 0; 1821 nstr = -1; 1822 if (s = field[2]) 1823 { 1824 s = expand(s, strbuf); 1825 if (test & TEST_EXPAND) 1826 { 1827 nstr = escape(s); 1828 #if _REG_nexec 1829 if (nstr != strlen(s)) 1830 nexec = nstr; 1831 #endif 1832 } 1833 } 1834 if (!(ans = field[(test & TEST_DECOMP) ? 2 : 3])) 1835 bad("NIL answer\n", NiL, NiL, 0, test); 1836 msg = field[4]; 1837 fflush(stdout); 1838 if (test & TEST_SUB) 1839 #if _REG_subcomp 1840 cflags |= REG_DELIMITED; 1841 #else 1842 continue; 1843 #endif 1844 #if !_REG_decomp 1845 if (test & TEST_DECOMP) 1846 continue; 1847 #endif 1848 1849 compile: 1850 1851 if (state.extracted || (skip & level)) 1852 continue; 1853 #if !(REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) 1854 #ifdef REG_EXTENDED 1855 if (REG_EXTENDED != 0 && (test & TEST_BRE)) 1856 #else 1857 if (test & TEST_BRE) 1858 #endif 1859 { 1860 test &= ~TEST_BRE; 1861 flags = cflags; 1862 state.which = "BRE"; 1863 } 1864 else 1865 #endif 1866 #ifdef REG_EXTENDED 1867 if (test & TEST_ERE) 1868 { 1869 test &= ~TEST_ERE; 1870 flags = cflags | REG_EXTENDED; 1871 state.which = "ERE"; 1872 } 1873 else 1874 #endif 1875 #ifdef REG_AUGMENTED 1876 if (test & TEST_ARE) 1877 { 1878 test &= ~TEST_ARE; 1879 flags = cflags | REG_AUGMENTED; 1880 state.which = "ARE"; 1881 } 1882 else 1883 #endif 1884 #ifdef REG_LITERAL 1885 if (test & TEST_LRE) 1886 { 1887 test &= ~TEST_LRE; 1888 flags = cflags | REG_LITERAL; 1889 state.which = "LRE"; 1890 } 1891 else 1892 #endif 1893 #ifdef REG_SHELL 1894 if (test & TEST_SRE) 1895 { 1896 test &= ~TEST_SRE; 1897 flags = cflags | REG_SHELL; 1898 state.which = "SRE"; 1899 } 1900 else 1901 #ifdef REG_AUGMENTED 1902 if (test & TEST_KRE) 1903 { 1904 test &= ~TEST_KRE; 1905 flags = cflags | REG_SHELL | REG_AUGMENTED; 1906 state.which = "KRE"; 1907 } 1908 else 1909 #endif 1910 #endif 1911 { 1912 if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY)) 1913 extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test|TEST_OK); 1914 continue; 1915 } 1916 if ((test & (TEST_QUERY|TEST_VERBOSE|TEST_VERIFY)) == TEST_VERBOSE) 1917 { 1918 printf("test %-3d %s ", state.lineno, state.which); 1919 quote(re, -1, test|TEST_DELIMIT); 1920 printf(" "); 1921 quote(s, nstr, test|TEST_DELIMIT); 1922 printf("\n"); 1923 } 1924 1925 nosub: 1926 fun = "regcomp"; 1927 #if _REG_nexec 1928 if (nstr >= 0 && nstr != strlen(s)) 1929 nexec = nstr; 1930 #endif 1931 1932 if (state.extracted || (skip & level)) 1933 continue; 1934 if (!(test & TEST_QUERY)) 1935 testno++; 1936 #ifdef REG_DISCIPLINE 1937 if (state.stack) 1938 stkset(stkstd, state.stack, 0); 1939 flags |= REG_DISCIPLINE; 1940 state.disc.ordinal = 0; 1941 sfstrseek(state.disc.sp, 0, SEEK_SET); 1942 #endif 1943 if (!(test & TEST_CATCH)) 1944 cret = regcomp(&preg, re, flags); 1945 else if (!(cret = setjmp(state.gotcha))) 1946 { 1947 alarm(HUNG); 1948 cret = regcomp(&preg, re, flags); 1949 alarm(0); 1950 } 1951 #if _REG_subcomp 1952 if (!cret && (test & TEST_SUB)) 1953 { 1954 fun = "regsubcomp"; 1955 p = re + preg.re_npat; 1956 if (!(test & TEST_CATCH)) 1957 cret = regsubcomp(&preg, p, NiL, 0, 0); 1958 else if (!(cret = setjmp(state.gotcha))) 1959 { 1960 alarm(HUNG); 1961 cret = regsubcomp(&preg, p, NiL, 0, 0); 1962 alarm(0); 1963 } 1964 if (!cret && *(p += preg.re_npat) && !(preg.re_sub->re_flags & REG_SUB_LAST)) 1965 { 1966 if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) 1967 continue; 1968 cret = REG_EFLAGS; 1969 } 1970 } 1971 #endif 1972 #if _REG_decomp 1973 if (!cret && (test & TEST_DECOMP)) 1974 { 1975 char buf[128]; 1976 1977 if ((j = nmatch) > sizeof(buf)) 1978 j = sizeof(buf); 1979 fun = "regdecomp"; 1980 p = re + preg.re_npat; 1981 if (!(test & TEST_CATCH)) 1982 i = regdecomp(&preg, -1, buf, j); 1983 else if (!(cret = setjmp(state.gotcha))) 1984 { 1985 alarm(HUNG); 1986 i = regdecomp(&preg, -1, buf, j); 1987 alarm(0); 1988 } 1989 if (!cret) 1990 { 1991 catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); 1992 if (i > j) 1993 { 1994 if (i != (strlen(ans) + 1)) 1995 { 1996 report("failed", fun, re, s, nstr, msg, flags, test); 1997 printf(" %d byte buffer supplied, %d byte buffer required\n", j, i); 1998 } 1999 } 2000 else if (strcmp(buf, ans)) 2001 { 2002 report("failed", fun, re, s, nstr, msg, flags, test); 2003 quote(ans, -1, test|TEST_DELIMIT); 2004 printf(" expected, "); 2005 quote(buf, -1, test|TEST_DELIMIT); 2006 printf(" returned\n"); 2007 } 2008 continue; 2009 } 2010 } 2011 #endif 2012 if (!cret) 2013 { 2014 if (!(flags & REG_NOSUB) && nsub < 0 && *ans == '(') 2015 { 2016 for (p = ans; *p; p++) 2017 if (*p == '(') 2018 nsub++; 2019 else if (*p == '{') 2020 nsub--; 2021 if (nsub >= 0) 2022 { 2023 if (test & TEST_IGNORE_OVER) 2024 { 2025 if (nmatch > nsub) 2026 nmatch = nsub + 1; 2027 } 2028 else if (nsub != preg.re_nsub) 2029 { 2030 if (nsub > preg.re_nsub) 2031 { 2032 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2033 skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2034 else 2035 { 2036 report("re_nsub incorrect", fun, re, NiL, -1, msg, flags, test); 2037 printf("at least %d expected, %d returned\n", nsub, preg.re_nsub); 2038 state.errors++; 2039 } 2040 } 2041 else 2042 nsub = preg.re_nsub; 2043 } 2044 } 2045 } 2046 if (!(test & (TEST_DECOMP|TEST_SUB)) && *ans && *ans != '(' && !streq(ans, "OK") && !streq(ans, "NOMATCH")) 2047 { 2048 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2049 skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2050 else if (!(test & TEST_LENIENT)) 2051 { 2052 report("failed", fun, re, NiL, -1, msg, flags, test); 2053 printf("%s expected, OK returned\n", ans); 2054 } 2055 catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); 2056 continue; 2057 } 2058 } 2059 else 2060 { 2061 if (test & TEST_LENIENT) 2062 /* we'll let it go this time */; 2063 else if (!*ans || ans[0]=='(' || cret == REG_BADPAT && streq(ans, "NOMATCH")) 2064 { 2065 got = 0; 2066 for (i = 1; i < elementsof(codes); i++) 2067 if (cret==codes[i].code) 2068 got = i; 2069 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2070 skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2071 else 2072 { 2073 report("failed", fun, re, NiL, -1, msg, flags, test); 2074 printf("%s returned: ", codes[got].name); 2075 error(&preg, cret); 2076 } 2077 } 2078 else 2079 { 2080 expected = got = 0; 2081 for (i = 1; i < elementsof(codes); i++) 2082 { 2083 if (streq(ans, codes[i].name)) 2084 expected = i; 2085 if (cret==codes[i].code) 2086 got = i; 2087 } 2088 if (!expected) 2089 { 2090 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2091 skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2092 else 2093 { 2094 report("failed: invalid error code", NiL, re, NiL, -1, msg, flags, test); 2095 printf("%s expected, %s returned\n", ans, codes[got].name); 2096 } 2097 } 2098 else if (cret != codes[expected].code && cret != REG_BADPAT) 2099 { 2100 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2101 skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2102 else if (test & TEST_IGNORE_ERROR) 2103 state.ignored++; 2104 else 2105 { 2106 report("should fail and did", fun, re, NiL, -1, msg, flags, test); 2107 printf("%s expected, %s returned: ", ans, codes[got].name); 2108 state.errors--; 2109 state.warnings++; 2110 error(&preg, cret); 2111 } 2112 } 2113 } 2114 goto compile; 2115 } 2116 2117 #if _REG_nexec 2118 execute: 2119 if (nexec >= 0) 2120 fun = "regnexec"; 2121 else 2122 #endif 2123 fun = "regexec"; 2124 2125 for (i = 0; i < elementsof(match); i++) 2126 match[i] = state.NOMATCH; 2127 2128 #if _REG_nexec 2129 if (nexec >= 0) 2130 { 2131 eret = regnexec(&preg, s, nexec, nmatch, match, eflags); 2132 s[nexec] = 0; 2133 } 2134 else 2135 #endif 2136 { 2137 if (!(test & TEST_CATCH)) 2138 eret = regexec(&preg, s, nmatch, match, eflags); 2139 else if (!(eret = setjmp(state.gotcha))) 2140 { 2141 alarm(HUNG); 2142 eret = regexec(&preg, s, nmatch, match, eflags); 2143 alarm(0); 2144 } 2145 } 2146 #if _REG_subcomp 2147 if ((test & TEST_SUB) && !eret) 2148 { 2149 fun = "regsubexec"; 2150 if (!(test & TEST_CATCH)) 2151 eret = regsubexec(&preg, s, nmatch, match); 2152 else if (!(eret = setjmp(state.gotcha))) 2153 { 2154 alarm(HUNG); 2155 eret = regsubexec(&preg, s, nmatch, match); 2156 alarm(0); 2157 } 2158 } 2159 #endif 2160 if (flags & REG_NOSUB) 2161 { 2162 if (eret) 2163 { 2164 if (eret != REG_NOMATCH || !streq(ans, "NOMATCH")) 2165 { 2166 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2167 skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2168 else 2169 { 2170 report("REG_NOSUB failed", fun, re, s, nstr, msg, flags, test); 2171 error(&preg, eret); 2172 } 2173 } 2174 } 2175 else if (streq(ans, "NOMATCH")) 2176 { 2177 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2178 skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); 2179 else 2180 { 2181 report("should fail and didn't", fun, re, s, nstr, msg, flags, test); 2182 error(&preg, eret); 2183 } 2184 } 2185 } 2186 else if (eret) 2187 { 2188 if (eret != REG_NOMATCH || !streq(ans, "NOMATCH")) 2189 { 2190 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2191 skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, nsub, skip, level, test|TEST_DELIMIT); 2192 else 2193 { 2194 report("failed", fun, re, s, nstr, msg, flags, test); 2195 if (eret != REG_NOMATCH) 2196 error(&preg, eret); 2197 else if (*ans) 2198 printf("expected: %s\n", ans); 2199 else 2200 printf("\n"); 2201 } 2202 } 2203 } 2204 else if (streq(ans, "NOMATCH")) 2205 { 2206 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2207 skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); 2208 else 2209 { 2210 report("should fail and didn't", fun, re, s, nstr, msg, flags, test); 2211 matchprint(match, nmatch, nsub, NiL, test); 2212 } 2213 } 2214 #if _REG_subcomp 2215 else if (test & TEST_SUB) 2216 { 2217 p = preg.re_sub->re_buf; 2218 if (strcmp(p, ans)) 2219 { 2220 report("failed", fun, re, s, nstr, msg, flags, test); 2221 quote(ans, -1, test|TEST_DELIMIT); 2222 printf(" expected, "); 2223 quote(p, -1, test|TEST_DELIMIT); 2224 printf(" returned\n"); 2225 } 2226 } 2227 #endif 2228 else if (!*ans) 2229 { 2230 if (match[0].rm_so != state.NOMATCH.rm_so) 2231 { 2232 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2233 skip = extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); 2234 else 2235 { 2236 report("failed: no match but match array assigned", NiL, re, s, nstr, msg, flags, test); 2237 matchprint(match, nmatch, nsub, NiL, test); 2238 } 2239 } 2240 } 2241 else if (matchcheck(match, nmatch, nsub, ans, re, s, nstr, flags, test)) 2242 { 2243 #if _REG_nexec 2244 if (nexec < 0 && !nonexec) 2245 { 2246 nexec = nstr >= 0 ? nstr : strlen(s); 2247 s[nexec] = '\n'; 2248 testno++; 2249 goto execute; 2250 } 2251 #endif 2252 if (!(test & (TEST_DECOMP|TEST_SUB|TEST_VERIFY)) && !nonosub) 2253 { 2254 if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) 2255 continue; 2256 flags |= REG_NOSUB; 2257 goto nosub; 2258 } 2259 if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY)) 2260 skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_OK); 2261 } 2262 else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2263 skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); 2264 if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) 2265 continue; 2266 goto compile; 2267 } 2268 if (test & TEST_SUMMARY) 2269 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); 2270 else if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS))) 2271 { 2272 printf("TEST\t%s", unit); 2273 if (subunit) 2274 printf(" %-.*s", subunitlen, subunit); 2275 printf(", %d test%s", testno, testno == 1 ? "" : "s"); 2276 if (state.ignored) 2277 printf(", %d ignored mismatche%s", state.ignored, state.ignored == 1 ? "" : "s"); 2278 if (state.warnings) 2279 printf(", %d warning%s", state.warnings, state.warnings == 1 ? "" : "s"); 2280 if (state.unspecified) 2281 printf(", %d unspecified difference%s", state.unspecified, state.unspecified == 1 ? "" : "s"); 2282 if (state.signals) 2283 printf(", %d signal%s", state.signals, state.signals == 1 ? "" : "s"); 2284 printf(", %d error%s\n", state.errors, state.errors == 1 ? "" : "s"); 2285 } 2286 if (fp != stdin) 2287 fclose(fp); 2288 } 2289 return 0; 2290 } 2291