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