OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [regexp/] [testdata/] [testregex.c] - Blame information for rev 801

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.