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