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