1#pragma prototyped noticed 2 3/* 4 * regex(3) test harness 5 * 6 * build: cc -o testregex testregex.c 7 * help: testregex --man 8 * note: REG_* features are detected by #ifdef; if REG_* are enums 9 * then supply #define REG_foo REG_foo for each enum REG_foo 10 * 11 * Glenn Fowler <gsf@research.att.com> 12 * AT&T Research 13 * 14 * PLEASE: publish your tests so everyone can benefit 15 * 16 * The following license covers testregex.c and all associated test data. 17 * 18 * Permission is hereby granted, free of charge, to any person obtaining a 19 * copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software 20 * without restriction, including without limitation the rights to use, 21 * copy, modify, merge, publish, distribute, and/or sell copies of the 22 * Software, and to permit persons to whom the Software is furnished to do 23 * so, subject to the following disclaimer: 24 * 25 * THIS SOFTWARE IS PROVIDED BY AT&T ``AS IS'' AND ANY EXPRESS OR IMPLIED 26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * IN NO EVENT SHALL AT&T BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37static 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 113typedef struct Disc_s 114{ 115 regdisc_t disc; 116 int ordinal; 117 Sfio_t* sp; 118} Disc_t; 119 120static void* 121compf(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 128static int 129execf(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 137static void* 138resizef(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 158static void 159help(int html) 160{ 161H("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n"); 162H("<HTML>\n"); 163H("<HEAD>\n"); 164H("<TITLE>testregex man document</TITLE>\n"); 165H("</HEAD>\n"); 166H("<BODY bgcolor=white>\n"); 167H("<PRE>\n"); 168T("NAME\n"); 169T(" testregex - regex(3) test harness\n"); 170T("\n"); 171T("SYNOPSIS\n"); 172T(" testregex [ options ]\n"); 173T("\n"); 174T("DESCRIPTION\n"); 175T(" testregex reads regex(3) test specifications, one per line, from the\n"); 176T(" standard input and writes one output line for each failed test. A\n"); 177T(" summary line is written after all tests are done. Each successful\n"); 178T(" test is run again with REG_NOSUB. Unsupported features are noted\n"); 179T(" before the first test, and tests requiring these features are\n"); 180T(" silently ignored.\n"); 181T("\n"); 182T("OPTIONS\n"); 183T(" -c catch signals and non-terminating calls\n"); 184T(" -e ignore error return mismatches\n"); 185T(" -h list help on standard error\n"); 186T(" -n do not repeat successful tests with regnexec()\n"); 187T(" -o ignore match[] overrun errors\n"); 188T(" -p ignore negative position mismatches\n"); 189T(" -s use stack instead of malloc\n"); 190T(" -x do not repeat successful tests with REG_NOSUB\n"); 191T(" -v list each test line\n"); 192T(" -A list failed test lines with actual answers\n"); 193T(" -B list all test lines with actual answers\n"); 194T(" -F list failed test lines\n"); 195T(" -P list passed test lines\n"); 196T(" -S output one summary line\n"); 197T("\n"); 198T("INPUT FORMAT\n"); 199T(" Input lines may be blank, a comment beginning with #, or a test\n"); 200T(" specification. A specification is five fields separated by one\n"); 201T(" or more tabs. NULL denotes the empty string and NIL denotes the\n"); 202T(" 0 pointer.\n"); 203T("\n"); 204T(" Field 1: the regex(3) flags to apply, one character per REG_feature\n"); 205T(" flag. The test is skipped if REG_feature is not supported by the\n"); 206T(" implementation. If the first character is not [BEASKLP] then the\n"); 207T(" specification is a global control line. One or more of [BEASKLP] may be\n"); 208T(" specified; the test will be repeated for each mode.\n"); 209T("\n"); 210T(" B basic BRE (grep, ed, sed)\n"); 211T(" E REG_EXTENDED ERE (egrep)\n"); 212T(" A REG_AUGMENTED ARE (egrep with negation)\n"); 213T(" S REG_SHELL SRE (sh glob)\n"); 214T(" K REG_SHELL|REG_AUGMENTED KRE (ksh glob)\n"); 215T(" L REG_LITERAL LRE (fgrep)\n"); 216T("\n"); 217T(" a REG_LEFT|REG_RIGHT implicit ^...$\n"); 218T(" b REG_NOTBOL lhs does not match ^\n"); 219T(" c REG_COMMENT ignore space and #...\\n\n"); 220T(" d REG_SHELL_DOT explicit leading . match\n"); 221T(" e REG_NOTEOL rhs does not match $\n"); 222T(" f REG_MULTIPLE multiple \\n separated patterns\n"); 223T(" g FNM_LEADING_DIR testfnmatch only -- match until /\n"); 224T(" h REG_MULTIREF multiple digit backref\n"); 225T(" i REG_ICASE ignore case\n"); 226T(" j REG_SPAN . matches \\n\n"); 227T(" k REG_ESCAPE \\ to ecape [...] delimiter\n"); 228T(" l REG_LEFT implicit ^...\n"); 229T(" m REG_MINIMAL minimal match\n"); 230T(" n REG_NEWLINE explicit \\n match\n"); 231T(" o REG_ENCLOSED (|&) magic inside [@|&](...)\n"); 232T(" p REG_SHELL_PATH explicit / match\n"); 233T(" q REG_DELIMITED delimited pattern\n"); 234T(" r REG_RIGHT implicit ...$\n"); 235T(" s REG_SHELL_ESCAPED \\ not special\n"); 236T(" t REG_MUSTDELIM all delimiters must be specified\n"); 237T(" u standard unspecified behavior -- errors not counted\n"); 238T(" v REG_CLASS_ESCAPE \\ special inside [...]\n"); 239T(" w REG_NOSUB no subexpression match array\n"); 240T(" x REG_LENIENT let some errors slide\n"); 241T(" y REG_LEFT regexec() implicit ^...\n"); 242T(" z REG_NULL NULL subexpressions ok\n"); 243T(" $ expand C \\c escapes in fields 2 and 3\n"); 244T(" / field 2 is a regsubcomp() expression\n"); 245T(" = field 3 is a regdecomp() expression\n"); 246T("\n"); 247T(" Field 1 control lines:\n"); 248T("\n"); 249T(" C set LC_COLLATE and LC_CTYPE to locale in field 2\n"); 250T("\n"); 251T(" ?test ... output field 5 if passed and != EXPECTED, silent otherwise\n"); 252T(" &test ... output field 5 if current and previous passed\n"); 253T(" |test ... output field 5 if current passed and previous failed\n"); 254T(" ; ... output field 2 if previous failed\n"); 255T(" {test ... skip if failed until }\n"); 256T(" } end of skip\n"); 257T("\n"); 258T(" : comment comment copied as output NOTE\n"); 259T(" :comment:test :comment: ignored\n"); 260T(" N[OTE] comment comment copied as output NOTE\n"); 261T(" T[EST] comment comment\n"); 262T("\n"); 263T(" number use number for nmatch (20 by default)\n"); 264T("\n"); 265T(" Field 2: the regular expression pattern; SAME uses the pattern from\n"); 266T(" the previous specification. RE_DUP_MAX inside {...} expands to the\n"); 267T(" value from <limits.h>.\n"); 268T("\n"); 269T(" Field 3: the string to match. X...{RE_DUP_MAX} expands to RE_DUP_MAX\n"); 270T(" copies of X.\n"); 271T("\n"); 272T(" Field 4: the test outcome. This is either one of the posix error\n"); 273T(" codes (with REG_ omitted) or the match array, a list of (m,n)\n"); 274T(" entries with m and n being first and last+1 positions in the\n"); 275T(" field 3 string, or NULL if REG_NOSUB is in effect and success\n"); 276T(" is expected. BADPAT is acceptable in place of any regcomp(3)\n"); 277T(" error code. The match[] array is initialized to (-2,-2) before\n"); 278T(" each test. All array elements from 0 to nmatch-1 must be specified\n"); 279T(" in the outcome. Unspecified endpoints (offset -1) are denoted by ?.\n"); 280T(" Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a\n"); 281T(" matched (?{...}) expression, where x is the text enclosed by {...},\n"); 282T(" o is the expression ordinal counting from 1, and n is the length of\n"); 283T(" the unmatched portion of the subject string. If x starts with a\n"); 284T(" number then that is the return value of re_execf(), otherwise 0 is\n"); 285T(" returned. RE_DUP_MAX[-+]N expands to the <limits.h> value -+N.\n"); 286T("\n"); 287T(" Field 5: optional comment appended to the report.\n"); 288T("\n"); 289T("CAVEAT\n"); 290T(" If a regex implementation misbehaves with memory then all bets are off.\n"); 291T("\n"); 292T("CONTRIBUTORS\n"); 293T(" Glenn Fowler gsf@research.att.com (ksh strmatch, regex extensions)\n"); 294T(" David Korn dgk@research.att.com (ksh glob matcher)\n"); 295T(" Doug McIlroy mcilroy@dartmouth.edu (ast regex/testre in C++)\n"); 296T(" Tom Lord lord@regexps.com (rx tests)\n"); 297T(" Henry Spencer henry@zoo.toronto.edu (original public regex)\n"); 298T(" Andrew Hume andrew@research.att.com (gre tests)\n"); 299T(" John Maddock John_Maddock@compuserve.com (regex++ tests)\n"); 300T(" Philip Hazel ph10@cam.ac.uk (pcre tests)\n"); 301T(" Ville Laurikari vl@iki.fi (libtre tests)\n"); 302H("</PRE>\n"); 303H("</BODY>\n"); 304H("</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 326static 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 524static 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 552static 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 573static void 574quote(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 653static void 654report(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 692static void 693error(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 716static void 717bad(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 724static int 725escape(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 840static void 841matchoffprint(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 857static void 858matchprint(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 881static int 882matchcheck(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 989static void 990sigunblock(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 1011static void 1012gotcha(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 1035static char* 1036getline(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 1060static unsigned long 1061note(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 1075static char ts[] = "\t\t\t\t\t\t\t"; 1076 1077static unsigned long 1078extract(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 1137static int 1138catchfree(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 1163static char* 1164expand(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 1216int 1217main(int argc, char** argv) 1218{ 1219 int flags; 1220 int cflags; 1221 int eflags; 1222 int nmatch; 1223 int nexec; 1224 int nstr; 1225 int cret; 1226 int eret; 1227 int nsub; 1228 int i; 1229 int j; 1230 int expected; 1231 int got; 1232 int locale; 1233 int subunitlen; 1234 int testno; 1235 unsigned long level; 1236 unsigned long skip; 1237 char* p; 1238 char* line; 1239 char* spec; 1240 char* re; 1241 char* s; 1242 char* ans; 1243 char* msg; 1244 char* fun; 1245 char* ppat; 1246 char* subunit; 1247 char* version; 1248 char* field[6]; 1249 char* delim[6]; 1250 FILE* fp; 1251 int tabs[6]; 1252 char unit[64]; 1253 regmatch_t match[100]; 1254 regex_t preg; 1255 1256 static char pat[32 * 1024]; 1257 static char patbuf[32 * 1024]; 1258 static char strbuf[32 * 1024]; 1259 1260 int nonosub = REG_NOSUB == 0; 1261 int nonexec = 0; 1262 1263 unsigned long test = 0; 1264 1265 static char* filter[] = { "-", 0 }; 1266 1267 state.NOMATCH.rm_so = state.NOMATCH.rm_eo = -2; 1268 p = unit; 1269 version = (char*)id + 10; 1270 while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace(*p)) 1271 p++; 1272 *p = 0; 1273 while ((p = *++argv) && *p == '-') 1274 for (;;) 1275 { 1276 switch (*++p) 1277 { 1278 case 0: 1279 break; 1280 case 'c': 1281 test |= TEST_CATCH; 1282 continue; 1283 case 'e': 1284 test |= TEST_IGNORE_ERROR; 1285 continue; 1286 case 'h': 1287 case '?': 1288 help(0); 1289 return 2; 1290 case '-': 1291 help(p[1] == 'h'); 1292 return 2; 1293 case 'n': 1294 nonexec = 1; 1295 continue; 1296 case 'o': 1297 test |= TEST_IGNORE_OVER; 1298 continue; 1299 case 'p': 1300 test |= TEST_IGNORE_POSITION; 1301 continue; 1302 case 's': 1303#ifdef REG_DISCIPLINE 1304 if (!(state.stack = stkalloc(stkstd, 0))) 1305 fprintf(stderr, "%s: out of space [stack]", unit); 1306 state.disc.disc.re_resizef = resizef; 1307 state.disc.disc.re_resizehandle = (void*)stkstd; 1308#endif 1309 continue; 1310 case 'x': 1311 nonosub = 1; 1312 continue; 1313 case 'v': 1314 test |= TEST_VERBOSE; 1315 continue; 1316 case 'A': 1317 test |= TEST_ACTUAL; 1318 continue; 1319 case 'B': 1320 test |= TEST_BASELINE; 1321 continue; 1322 case 'F': 1323 test |= TEST_FAIL; 1324 continue; 1325 case 'P': 1326 test |= TEST_PASS; 1327 continue; 1328 case 'S': 1329 test |= TEST_SUMMARY; 1330 continue; 1331 default: 1332 fprintf(stderr, "%s: %c: invalid option\n", unit, *p); 1333 return 2; 1334 } 1335 break; 1336 } 1337 if (!*argv) 1338 argv = filter; 1339 locale = 0; 1340 while (state.file = *argv++) 1341 { 1342 if (streq(state.file, "-") || streq(state.file, "/dev/stdin") || streq(state.file, "/dev/fd/0")) 1343 { 1344 state.file = 0; 1345 fp = stdin; 1346 } 1347 else if (!(fp = fopen(state.file, "r"))) 1348 { 1349 fprintf(stderr, "%s: %s: cannot read\n", unit, state.file); 1350 return 2; 1351 } 1352 testno = state.errors = state.ignored = state.lineno = state.passed = 1353 state.signals = state.unspecified = state.warnings = 0; 1354 skip = 0; 1355 level = 1; 1356 if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) 1357 { 1358 printf("TEST\t%s ", unit); 1359 if (s = state.file) 1360 { 1361 subunit = p = 0; 1362 for (;;) 1363 { 1364 switch (*s++) 1365 { 1366 case 0: 1367 break; 1368 case '/': 1369 subunit = s; 1370 continue; 1371 case '.': 1372 p = s - 1; 1373 continue; 1374 default: 1375 continue; 1376 } 1377 break; 1378 } 1379 if (!subunit) 1380 subunit = state.file; 1381 if (p < subunit) 1382 p = s - 1; 1383 subunitlen = p - subunit; 1384 printf("%-.*s ", subunitlen, subunit); 1385 } 1386 else 1387 subunit = 0; 1388 for (s = version; *s && (*s != ' ' || *(s + 1) != '$'); s++) 1389 putchar(*s); 1390 if (test & TEST_CATCH) 1391 printf(", catch"); 1392 if (test & TEST_IGNORE_ERROR) 1393 printf(", ignore error code mismatches"); 1394 if (test & TEST_IGNORE_POSITION) 1395 printf(", ignore negative position mismatches"); 1396#ifdef REG_DISCIPLINE 1397 if (state.stack) 1398 printf(", stack"); 1399#endif 1400 if (test & TEST_VERBOSE) 1401 printf(", verbose"); 1402 printf("\n"); 1403#ifdef REG_VERSIONID 1404 if (regerror(REG_VERSIONID, NiL, pat, sizeof(pat)) > 0) 1405 s = pat; 1406 else 1407#endif 1408#ifdef REG_TEST_VERSION 1409 s = REG_TEST_VERSION; 1410#else 1411 s = "regex"; 1412#endif 1413 printf("NOTE\t%s\n", s); 1414 if (elementsof(unsupported) > 1) 1415 { 1416#if (REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) || !defined(REG_EXTENDED) 1417 i = 0; 1418#else 1419 i = REG_EXTENDED != 0; 1420#endif 1421 for (got = 0; i < elementsof(unsupported) - 1; i++) 1422 { 1423 if (!got) 1424 { 1425 got = 1; 1426 printf("NOTE\tunsupported: %s", unsupported[i]); 1427 } 1428 else 1429 printf(",%s", unsupported[i]); 1430 } 1431 if (got) 1432 printf("\n"); 1433 } 1434 } 1435#ifdef REG_DISCIPLINE 1436 state.disc.disc.re_version = REG_VERSION; 1437 state.disc.disc.re_compf = compf; 1438 state.disc.disc.re_execf = execf; 1439 if (!(state.disc.sp = sfstropen())) 1440 bad("out of space [discipline string stream]\n", NiL, NiL, 0, 0); 1441 preg.re_disc = &state.disc.disc; 1442#endif 1443 if (test & TEST_CATCH) 1444 { 1445 signal(SIGALRM, gotcha); 1446 signal(SIGBUS, gotcha); 1447 signal(SIGSEGV, gotcha); 1448 } 1449 while (p = getline(fp)) 1450 { 1451 1452 /* parse: */ 1453 1454 line = p; 1455 if (*p == ':' && !isspace(*(p + 1))) 1456 { 1457 while (*++p && *p != ':'); 1458 if (!*p++) 1459 { 1460 if (test & TEST_BASELINE) 1461 printf("%s\n", line); 1462 continue; 1463 } 1464 } 1465 while (isspace(*p)) 1466 p++; 1467 if (*p == 0 || *p == '#' || *p == 'T') 1468 { 1469 if (test & TEST_BASELINE) 1470 printf("%s\n", line); 1471 continue; 1472 } 1473 if (*p == ':' || *p == 'N') 1474 { 1475 if (test & TEST_BASELINE) 1476 printf("%s\n", line); 1477 else if (!(test & (TEST_ACTUAL|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) 1478 { 1479 while (*++p && !isspace(*p)); 1480 while (isspace(*p)) 1481 p++; 1482 printf("NOTE %s\n", p); 1483 } 1484 continue; 1485 } 1486 j = 0; 1487 i = 0; 1488 field[i++] = p; 1489 for (;;) 1490 { 1491 switch (*p++) 1492 { 1493 case 0: 1494 p--; 1495 j = 0; 1496 goto checkfield; 1497 case '\t': 1498 *(delim[i] = p - 1) = 0; 1499 j = 1; 1500 checkfield: 1501 s = field[i - 1]; 1502 if (streq(s, "NIL")) 1503 field[i - 1] = 0; 1504 else if (streq(s, "NULL")) 1505 *s = 0; 1506 while (*p == '\t') 1507 { 1508 p++; 1509 j++; 1510 } 1511 tabs[i - 1] = j; 1512 if (!*p) 1513 break; 1514 if (i >= elementsof(field)) 1515 bad("too many fields\n", NiL, NiL, 0, 0); 1516 field[i++] = p; 1517 /*FALLTHROUGH*/ 1518 default: 1519 continue; 1520 } 1521 break; 1522 } 1523 if (!(spec = field[0])) 1524 bad("NIL spec\n", NiL, NiL, 0, 0); 1525 1526 /* interpret: */ 1527 1528 cflags = REG_TEST_DEFAULT; 1529 eflags = REG_EXEC_DEFAULT; 1530 test &= TEST_GLOBAL; 1531 state.extracted = 0; 1532 nmatch = 20; 1533 nsub = -1; 1534 for (p = spec; *p; p++) 1535 { 1536 if (isdigit(*p)) 1537 { 1538 nmatch = strtol(p, &p, 10); 1539 if (nmatch >= elementsof(match)) 1540 bad("nmatch must be < 100\n", NiL, NiL, 0, 0); 1541 p--; 1542 continue; 1543 } 1544 switch (*p) 1545 { 1546 case 'A': 1547 test |= TEST_ARE; 1548 continue; 1549 case 'B': 1550 test |= TEST_BRE; 1551 continue; 1552 case 'C': 1553 if (!(test & TEST_QUERY) && !(skip & level)) 1554 bad("locale must be nested\n", NiL, NiL, 0, 0); 1555 test &= ~TEST_QUERY; 1556 if (locale) 1557 bad("locale nesting not supported\n", NiL, NiL, 0, 0); 1558 if (i != 2) 1559 bad("locale field expected\n", NiL, NiL, 0, 0); 1560 if (!(skip & level)) 1561 { 1562#if defined(LC_COLLATE) && defined(LC_CTYPE) 1563 s = field[1]; 1564 if (!s || streq(s, "POSIX")) 1565 s = "C"; 1566 if ((ans = setlocale(LC_COLLATE, s)) && streq(ans, "POSIX")) 1567 ans = "C"; 1568 if (!ans || !streq(ans, s) && streq(s, "C")) 1569 ans = 0; 1570 else if ((ans = setlocale(LC_CTYPE, s)) && streq(ans, "POSIX")) 1571 ans = "C"; 1572 if (!ans || !streq(ans, s) && streq(s, "C")) 1573 skip = note(level, s, skip, test); 1574 else 1575 { 1576 if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) 1577 printf("NOTE \"%s\" locale\n", s); 1578 locale = level; 1579 } 1580#else 1581 skip = note(level, skip, test, "locales not supported"); 1582#endif 1583 } 1584 cflags = NOTEST; 1585 continue; 1586 case 'E': 1587 test |= TEST_ERE; 1588 continue; 1589 case 'K': 1590 test |= TEST_KRE; 1591 continue; 1592 case 'L': 1593 test |= TEST_LRE; 1594 continue; 1595 case 'S': 1596 test |= TEST_SRE; 1597 continue; 1598 1599 case 'a': 1600 cflags |= REG_LEFT|REG_RIGHT; 1601 continue; 1602 case 'b': 1603 eflags |= REG_NOTBOL; 1604 continue; 1605 case 'c': 1606 cflags |= REG_COMMENT; 1607 continue; 1608 case 'd': 1609 cflags |= REG_SHELL_DOT; 1610 continue; 1611 case 'e': 1612 eflags |= REG_NOTEOL; 1613 continue; 1614 case 'f': 1615 cflags |= REG_MULTIPLE; 1616 continue; 1617 case 'g': 1618 cflags |= NOTEST; 1619 continue; 1620 case 'h': 1621 cflags |= REG_MULTIREF; 1622 continue; 1623 case 'i': 1624 cflags |= REG_ICASE; 1625 continue; 1626 case 'j': 1627 cflags |= REG_SPAN; 1628 continue; 1629 case 'k': 1630 cflags |= REG_ESCAPE; 1631 continue; 1632 case 'l': 1633 cflags |= REG_LEFT; 1634 continue; 1635 case 'm': 1636 cflags |= REG_MINIMAL; 1637 continue; 1638 case 'n': 1639 cflags |= REG_NEWLINE; 1640 continue; 1641 case 'o': 1642 cflags |= REG_SHELL_GROUP; 1643 continue; 1644 case 'p': 1645 cflags |= REG_SHELL_PATH; 1646 continue; 1647 case 'q': 1648 cflags |= REG_DELIMITED; 1649 continue; 1650 case 'r': 1651 cflags |= REG_RIGHT; 1652 continue; 1653 case 's': 1654 cflags |= REG_SHELL_ESCAPED; 1655 continue; 1656 case 't': 1657 cflags |= REG_MUSTDELIM; 1658 continue; 1659 case 'u': 1660 test |= TEST_UNSPECIFIED; 1661 continue; 1662 case 'v': 1663 cflags |= REG_CLASS_ESCAPE; 1664 continue; 1665 case 'w': 1666 cflags |= REG_NOSUB; 1667 continue; 1668 case 'x': 1669 if (REG_LENIENT) 1670 cflags |= REG_LENIENT; 1671 else 1672 test |= TEST_LENIENT; 1673 continue; 1674 case 'y': 1675 eflags |= REG_LEFT; 1676 continue; 1677 case 'z': 1678 cflags |= REG_NULL; 1679 continue; 1680 1681 case '$': 1682 test |= TEST_EXPAND; 1683 continue; 1684 1685 case '/': 1686 test |= TEST_SUB; 1687 continue; 1688 1689 case '=': 1690 test |= TEST_DECOMP; 1691 continue; 1692 1693 case '?': 1694 test |= TEST_VERIFY; 1695 test &= ~(TEST_AND|TEST_OR); 1696 state.verify = state.passed; 1697 continue; 1698 case '&': 1699 test |= TEST_VERIFY|TEST_AND; 1700 test &= ~TEST_OR; 1701 continue; 1702 case '|': 1703 test |= TEST_VERIFY|TEST_OR; 1704 test &= ~TEST_AND; 1705 continue; 1706 case ';': 1707 test |= TEST_OR; 1708 test &= ~TEST_AND; 1709 continue; 1710 1711 case '{': 1712 level <<= 1; 1713 if (skip & (level >> 1)) 1714 { 1715 skip |= level; 1716 cflags = NOTEST; 1717 } 1718 else 1719 { 1720 skip &= ~level; 1721 test |= TEST_QUERY; 1722 } 1723 continue; 1724 case '}': 1725 if (level == 1) 1726 bad("invalid {...} nesting\n", NiL, NiL, 0, 0); 1727 if ((skip & level) && !(skip & (level>>1))) 1728 { 1729 if (!(test & (TEST_BASELINE|TEST_SUMMARY))) 1730 { 1731 if (test & (TEST_ACTUAL|TEST_FAIL)) 1732 printf("}\n"); 1733 else if (!(test & TEST_PASS)) 1734 printf("-%d\n", state.lineno); 1735 } 1736 } 1737#if defined(LC_COLLATE) && defined(LC_CTYPE) 1738 else if (locale & level) 1739 { 1740 locale = 0; 1741 if (!(skip & level)) 1742 { 1743 s = "C"; 1744 setlocale(LC_COLLATE, s); 1745 setlocale(LC_CTYPE, s); 1746 if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) 1747 printf("NOTE \"%s\" locale\n", s); 1748 else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_PASS)) 1749 printf("}\n"); 1750 } 1751 else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL)) 1752 printf("}\n"); 1753 } 1754#endif 1755 level >>= 1; 1756 cflags = NOTEST; 1757 continue; 1758 1759 default: 1760 bad("bad spec\n", spec, NiL, 0, test); 1761 break; 1762 1763 } 1764 break; 1765 } 1766 if ((cflags|eflags) == NOTEST || (skip & level) && (test & TEST_BASELINE)) 1767 { 1768 if (test & TEST_BASELINE) 1769 { 1770 while (i > 1) 1771 *delim[--i] = '\t'; 1772 printf("%s\n", line); 1773 } 1774 continue; 1775 } 1776 if (test & TEST_OR) 1777 { 1778 if (!(test & TEST_VERIFY)) 1779 { 1780 test &= ~TEST_OR; 1781 if (state.passed == state.verify && i > 1) 1782 printf("NOTE\t%s\n", field[1]); 1783 continue; 1784 } 1785 else if (state.passed > state.verify) 1786 continue; 1787 } 1788 else if (test & TEST_AND) 1789 { 1790 if (state.passed == state.verify) 1791 continue; 1792 state.passed = state.verify; 1793 } 1794 if (i < ((test & TEST_DECOMP) ? 3 : 4)) 1795 bad("too few fields\n", NiL, NiL, 0, test); 1796 while (i < elementsof(field)) 1797 field[i++] = 0; 1798 if (re = field[1]) 1799 { 1800 if (streq(re, "SAME")) 1801 { 1802 re = ppat; 1803 test |= TEST_SAME; 1804 } 1805 else 1806 { 1807 if (test & TEST_EXPAND) 1808 escape(re); 1809 re = expand(re, patbuf); 1810 strcpy(ppat = pat, re); 1811 } 1812 } 1813 else 1814 ppat = 0; 1815 nstr = -1; 1816 if (s = field[2]) 1817 { 1818 s = expand(s, strbuf); 1819 if (test & TEST_EXPAND) 1820 { 1821 nstr = escape(s); 1822#if _REG_nexec 1823 if (nstr != strlen(s)) 1824 nexec = nstr; 1825#endif 1826 } 1827 } 1828 if (!(ans = field[(test & TEST_DECOMP) ? 2 : 3])) 1829 bad("NIL answer\n", NiL, NiL, 0, test); 1830 msg = field[4]; 1831 fflush(stdout); 1832 if (test & TEST_SUB) 1833#if _REG_subcomp 1834 cflags |= REG_DELIMITED; 1835#else 1836 continue; 1837#endif 1838#if !_REG_decomp 1839 if (test & TEST_DECOMP) 1840 continue; 1841#endif 1842 1843 compile: 1844 1845 if (state.extracted || (skip & level)) 1846 continue; 1847#if !(REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) 1848#ifdef REG_EXTENDED 1849 if (REG_EXTENDED != 0 && (test & TEST_BRE)) 1850#else 1851 if (test & TEST_BRE) 1852#endif 1853 { 1854 test &= ~TEST_BRE; 1855 flags = cflags; 1856 state.which = "BRE"; 1857 } 1858 else 1859#endif 1860#ifdef REG_EXTENDED 1861 if (test & TEST_ERE) 1862 { 1863 test &= ~TEST_ERE; 1864 flags = cflags | REG_EXTENDED; 1865 state.which = "ERE"; 1866 } 1867 else 1868#endif 1869#ifdef REG_AUGMENTED 1870 if (test & TEST_ARE) 1871 { 1872 test &= ~TEST_ARE; 1873 flags = cflags | REG_AUGMENTED; 1874 state.which = "ARE"; 1875 } 1876 else 1877#endif 1878#ifdef REG_LITERAL 1879 if (test & TEST_LRE) 1880 { 1881 test &= ~TEST_LRE; 1882 flags = cflags | REG_LITERAL; 1883 state.which = "LRE"; 1884 } 1885 else 1886#endif 1887#ifdef REG_SHELL 1888 if (test & TEST_SRE) 1889 { 1890 test &= ~TEST_SRE; 1891 flags = cflags | REG_SHELL; 1892 state.which = "SRE"; 1893 } 1894 else 1895#ifdef REG_AUGMENTED 1896 if (test & TEST_KRE) 1897 { 1898 test &= ~TEST_KRE; 1899 flags = cflags | REG_SHELL | REG_AUGMENTED; 1900 state.which = "KRE"; 1901 } 1902 else 1903#endif 1904#endif 1905 { 1906 if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY)) 1907 extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test|TEST_OK); 1908 continue; 1909 } 1910 if ((test & (TEST_QUERY|TEST_VERBOSE|TEST_VERIFY)) == TEST_VERBOSE) 1911 { 1912 printf("test %-3d %s ", state.lineno, state.which); 1913 quote(re, -1, test|TEST_DELIMIT); 1914 printf(" "); 1915 quote(s, nstr, test|TEST_DELIMIT); 1916 printf("\n"); 1917 } 1918 1919 nosub: 1920 fun = "regcomp"; 1921#if _REG_nexec 1922 if (nstr >= 0 && nstr != strlen(s)) 1923 nexec = nstr; 1924 1925 else 1926#endif 1927 nexec = -1; 1928 if (state.extracted || (skip & level)) 1929 continue; 1930 if (!(test & TEST_QUERY)) 1931 testno++; 1932#ifdef REG_DISCIPLINE 1933 if (state.stack) 1934 stkset(stkstd, state.stack, 0); 1935 flags |= REG_DISCIPLINE; 1936 state.disc.ordinal = 0; 1937 sfstrseek(state.disc.sp, 0, SEEK_SET); 1938#endif 1939 if (!(test & TEST_CATCH)) 1940 cret = regcomp(&preg, re, flags); 1941 else if (!(cret = setjmp(state.gotcha))) 1942 { 1943 alarm(HUNG); 1944 cret = regcomp(&preg, re, flags); 1945 alarm(0); 1946 } 1947#if _REG_subcomp 1948 if (!cret && (test & TEST_SUB)) 1949 { 1950 fun = "regsubcomp"; 1951 p = re + preg.re_npat; 1952 if (!(test & TEST_CATCH)) 1953 cret = regsubcomp(&preg, p, NiL, 0, 0); 1954 else if (!(cret = setjmp(state.gotcha))) 1955 { 1956 alarm(HUNG); 1957 cret = regsubcomp(&preg, p, NiL, 0, 0); 1958 alarm(0); 1959 } 1960 if (!cret && *(p += preg.re_npat) && !(preg.re_sub->re_flags & REG_SUB_LAST)) 1961 { 1962 if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) 1963 continue; 1964 cret = REG_EFLAGS; 1965 } 1966 } 1967#endif 1968#if _REG_decomp 1969 if (!cret && (test & TEST_DECOMP)) 1970 { 1971 char buf[128]; 1972 1973 if ((j = nmatch) > sizeof(buf)) 1974 j = sizeof(buf); 1975 fun = "regdecomp"; 1976 p = re + preg.re_npat; 1977 if (!(test & TEST_CATCH)) 1978 i = regdecomp(&preg, -1, buf, j); 1979 else if (!(cret = setjmp(state.gotcha))) 1980 { 1981 alarm(HUNG); 1982 i = regdecomp(&preg, -1, buf, j); 1983 alarm(0); 1984 } 1985 if (!cret) 1986 { 1987 catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); 1988 if (i > j) 1989 { 1990 if (i != (strlen(ans) + 1)) 1991 { 1992 report("failed", fun, re, s, nstr, msg, flags, test); 1993 printf(" %d byte buffer supplied, %d byte buffer required\n", j, i); 1994 } 1995 } 1996 else if (strcmp(buf, ans)) 1997 { 1998 report("failed", fun, re, s, nstr, msg, flags, test); 1999 quote(ans, -1, test|TEST_DELIMIT); 2000 printf(" expected, "); 2001 quote(buf, -1, test|TEST_DELIMIT); 2002 printf(" returned\n"); 2003 } 2004 continue; 2005 } 2006 } 2007#endif 2008 if (!cret) 2009 { 2010 if (!(flags & REG_NOSUB) && nsub < 0 && *ans == '(') 2011 { 2012 for (p = ans; *p; p++) 2013 if (*p == '(') 2014 nsub++; 2015 else if (*p == '{') 2016 nsub--; 2017 if (nsub >= 0) 2018 { 2019 if (test & TEST_IGNORE_OVER) 2020 { 2021 if (nmatch > nsub) 2022 nmatch = nsub + 1; 2023 } 2024 else if (nsub != preg.re_nsub) 2025 { 2026 if (nsub > preg.re_nsub) 2027 { 2028 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2029 skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2030 else 2031 { 2032 report("re_nsub incorrect", fun, re, NiL, -1, msg, flags, test); 2033 printf("at least %d expected, %d returned\n", nsub, preg.re_nsub); 2034 state.errors++; 2035 } 2036 } 2037 else 2038 nsub = preg.re_nsub; 2039 } 2040 } 2041 } 2042 if (!(test & (TEST_DECOMP|TEST_SUB)) && *ans && *ans != '(' && !streq(ans, "OK") && !streq(ans, "NOMATCH")) 2043 { 2044 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2045 skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2046 else if (!(test & TEST_LENIENT)) 2047 { 2048 report("failed", fun, re, NiL, -1, msg, flags, test); 2049 printf("%s expected, OK returned\n", ans); 2050 } 2051 catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); 2052 continue; 2053 } 2054 } 2055 else 2056 { 2057 if (test & TEST_LENIENT) 2058 /* we'll let it go this time */; 2059 else if (!*ans || ans[0]=='(' || cret == REG_BADPAT && streq(ans, "NOMATCH")) 2060 { 2061 got = 0; 2062 for (i = 1; i < elementsof(codes); i++) 2063 if (cret==codes[i].code) 2064 got = i; 2065 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2066 skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2067 else 2068 { 2069 report("failed", fun, re, NiL, -1, msg, flags, test); 2070 printf("%s returned: ", codes[got].name); 2071 error(&preg, cret); 2072 } 2073 } 2074 else 2075 { 2076 expected = got = 0; 2077 for (i = 1; i < elementsof(codes); i++) 2078 { 2079 if (streq(ans, codes[i].name)) 2080 expected = i; 2081 if (cret==codes[i].code) 2082 got = i; 2083 } 2084 if (!expected) 2085 { 2086 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2087 skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2088 else 2089 { 2090 report("failed: invalid error code", NiL, re, NiL, -1, msg, flags, test); 2091 printf("%s expected, %s returned\n", ans, codes[got].name); 2092 } 2093 } 2094 else if (cret != codes[expected].code && cret != REG_BADPAT) 2095 { 2096 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2097 skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2098 else if (test & TEST_IGNORE_ERROR) 2099 state.ignored++; 2100 else 2101 { 2102 report("should fail and did", fun, re, NiL, -1, msg, flags, test); 2103 printf("%s expected, %s returned: ", ans, codes[got].name); 2104 state.errors--; 2105 state.warnings++; 2106 error(&preg, cret); 2107 } 2108 } 2109 } 2110 goto compile; 2111 } 2112 2113#if _REG_nexec 2114 execute: 2115 if (nexec >= 0) 2116 fun = "regnexec"; 2117 else 2118#endif 2119 fun = "regexec"; 2120 2121 for (i = 0; i < elementsof(match); i++) 2122 match[i] = state.NOMATCH; 2123 2124#if _REG_nexec 2125 if (nexec >= 0) 2126 { 2127 eret = regnexec(&preg, s, nexec, nmatch, match, eflags); 2128 s[nexec] = 0; 2129 } 2130 else 2131#endif 2132 { 2133 if (!(test & TEST_CATCH)) 2134 eret = regexec(&preg, s, nmatch, match, eflags); 2135 else if (!(eret = setjmp(state.gotcha))) 2136 { 2137 alarm(HUNG); 2138 eret = regexec(&preg, s, nmatch, match, eflags); 2139 alarm(0); 2140 } 2141 } 2142#if _REG_subcomp 2143 if ((test & TEST_SUB) && !eret) 2144 { 2145 fun = "regsubexec"; 2146 if (!(test & TEST_CATCH)) 2147 eret = regsubexec(&preg, s, nmatch, match); 2148 else if (!(eret = setjmp(state.gotcha))) 2149 { 2150 alarm(HUNG); 2151 eret = regsubexec(&preg, s, nmatch, match); 2152 alarm(0); 2153 } 2154 } 2155#endif 2156 if (flags & REG_NOSUB) 2157 { 2158 if (eret) 2159 { 2160 if (eret != REG_NOMATCH || !streq(ans, "NOMATCH")) 2161 { 2162 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2163 skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, 0, skip, level, test|TEST_DELIMIT); 2164 else 2165 { 2166 report("REG_NOSUB failed", fun, re, s, nstr, msg, flags, test); 2167 error(&preg, eret); 2168 } 2169 } 2170 } 2171 else if (streq(ans, "NOMATCH")) 2172 { 2173 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2174 skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); 2175 else 2176 { 2177 report("should fail and didn't", fun, re, s, nstr, msg, flags, test); 2178 error(&preg, eret); 2179 } 2180 } 2181 } 2182 else if (eret) 2183 { 2184 if (eret != REG_NOMATCH || !streq(ans, "NOMATCH")) 2185 { 2186 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2187 skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, nsub, skip, level, test|TEST_DELIMIT); 2188 else 2189 { 2190 report("failed", fun, re, s, nstr, msg, flags, test); 2191 if (eret != REG_NOMATCH) 2192 error(&preg, eret); 2193 else if (*ans) 2194 printf("expected: %s\n", ans); 2195 else 2196 printf("\n"); 2197 } 2198 } 2199 } 2200 else if (streq(ans, "NOMATCH")) 2201 { 2202 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2203 skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); 2204 else 2205 { 2206 report("should fail and didn't", fun, re, s, nstr, msg, flags, test); 2207 matchprint(match, nmatch, nsub, NiL, test); 2208 } 2209 } 2210#if _REG_subcomp 2211 else if (test & TEST_SUB) 2212 { 2213 p = preg.re_sub->re_buf; 2214 if (strcmp(p, ans)) 2215 { 2216 report("failed", fun, re, s, nstr, msg, flags, test); 2217 quote(ans, -1, test|TEST_DELIMIT); 2218 printf(" expected, "); 2219 quote(p, -1, test|TEST_DELIMIT); 2220 printf(" returned\n"); 2221 } 2222 } 2223#endif 2224 else if (!*ans) 2225 { 2226 if (match[0].rm_so != state.NOMATCH.rm_so) 2227 { 2228 if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2229 skip = extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); 2230 else 2231 { 2232 report("failed: no match but match array assigned", NiL, re, s, nstr, msg, flags, test); 2233 matchprint(match, nmatch, nsub, NiL, test); 2234 } 2235 } 2236 } 2237 else if (matchcheck(match, nmatch, nsub, ans, re, s, nstr, flags, test)) 2238 { 2239#if _REG_nexec 2240 if (nexec < 0 && !nonexec) 2241 { 2242 nexec = nstr >= 0 ? nstr : strlen(s); 2243 s[nexec] = '\n'; 2244 testno++; 2245 goto execute; 2246 } 2247#endif 2248 if (!(test & (TEST_DECOMP|TEST_SUB|TEST_VERIFY)) && !nonosub) 2249 { 2250 if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) 2251 continue; 2252 flags |= REG_NOSUB; 2253 goto nosub; 2254 } 2255 if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY)) 2256 skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_OK); 2257 } 2258 else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) 2259 skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); 2260 if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) 2261 continue; 2262 goto compile; 2263 } 2264 if (test & TEST_SUMMARY) 2265 printf("tests=%-4d errors=%-4d warnings=%-2d ignored=%-2d unspecified=%-2d signals=%d\n", testno, state.errors, state.warnings, state.ignored, state.unspecified, state.signals); 2266 else if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS))) 2267 { 2268 printf("TEST\t%s", unit); 2269 if (subunit) 2270 printf(" %-.*s", subunitlen, subunit); 2271 printf(", %d test%s", testno, testno == 1 ? "" : "s"); 2272 if (state.ignored) 2273 printf(", %d ignored mismatche%s", state.ignored, state.ignored == 1 ? "" : "s"); 2274 if (state.warnings) 2275 printf(", %d warning%s", state.warnings, state.warnings == 1 ? "" : "s"); 2276 if (state.unspecified) 2277 printf(", %d unspecified difference%s", state.unspecified, state.unspecified == 1 ? "" : "s"); 2278 if (state.signals) 2279 printf(", %d signal%s", state.signals, state.signals == 1 ? "" : "s"); 2280 printf(", %d error%s\n", state.errors, state.errors == 1 ? "" : "s"); 2281 } 2282 if (fp != stdin) 2283 fclose(fp); 2284 } 2285 return 0; 2286} 2287