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