1 /* $NetBSD: main.c,v 1.2 2011/09/16 16:13:18 plunky Exp $ */
4 * Copyright (c) 1993 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/types.h>
38 #include "test_regex.h"
45 int copts
= REG_EXTENDED
;
47 regoff_t startoff
= 0;
50 static char empty
= '\0';
52 static char *eprint(int);
53 static int efind(char *);
56 * main - do the simple case, hand off to regress() for regression
59 main(int argc
, char *argv
[])
75 while ((c
= getopt(argc
, argv
, "c:e:S:E:x")) != -1)
77 case 'c': /* compile options */
78 copts
= options('c', optarg
);
80 case 'e': /* execute options */
81 eopts
= options('e', optarg
);
83 case 'S': /* start offset */
84 startoff
= (regoff_t
)atoi(optarg
);
86 case 'E': /* end offset */
87 endoff
= (regoff_t
)atoi(optarg
);
89 case 'x': /* Debugging. */
98 fprintf(stderr
, "usage: %s ", progname
);
99 fprintf(stderr
, "[-c copt][-C][-d] [re]\n");
103 if (optind
>= argc
) {
108 err
= regcomp(&re
, argv
[optind
++], copts
);
110 len
= regerror(err
, &re
, erbuf
, sizeof(erbuf
));
111 fprintf(stderr
, "error %s, %zd/%zd `%s'\n",
112 eprint(err
), len
, (size_t)sizeof(erbuf
), erbuf
);
115 regprint(&re
, stdout
);
117 if (optind
>= argc
) {
122 if (eopts
®_STARTEND
) {
123 subs
[0].rm_so
= startoff
;
124 subs
[0].rm_eo
= strlen(argv
[optind
]) - endoff
;
126 err
= regexec(&re
, argv
[optind
], (size_t)NS
, subs
, eopts
);
128 len
= regerror(err
, &re
, erbuf
, sizeof(erbuf
));
129 fprintf(stderr
, "error %s, %zd/%zd `%s'\n",
130 eprint(err
), len
, (size_t)sizeof(erbuf
), erbuf
);
133 if (!(copts
®_NOSUB
)) {
134 len
= (int)(subs
[0].rm_eo
- subs
[0].rm_so
);
135 if (subs
[0].rm_so
!= -1) {
137 printf("match `%.*s'\n", (int)len
,
138 argv
[optind
] + subs
[0].rm_so
);
140 printf("match `'@%.1s\n",
141 argv
[optind
] + subs
[0].rm_so
);
143 for (i
= 1; i
< NS
; i
++)
144 if (subs
[i
].rm_so
!= -1)
145 printf("(%d) `%.*s'\n", i
,
146 (int)(subs
[i
].rm_eo
- subs
[i
].rm_so
),
147 argv
[optind
] + subs
[i
].rm_so
);
153 * regress - main loop of regression test
165 const char *badpat
= "invalid regular expression";
167 const char *bpname
= "REG_BADPAT";
170 while (fgets(inbuf
, sizeof(inbuf
), in
) != NULL
) {
172 if (inbuf
[0] == '#' || inbuf
[0] == '\n')
173 continue; /* NOTE CONTINUE */
174 inbuf
[strlen(inbuf
)-1] = '\0'; /* get rid of stupid \n */
176 fprintf(stdout
, "%d:\n", line
);
177 nf
= split(inbuf
, f
, MAXF
, "\t\t");
179 fprintf(stderr
, "bad input, line %d\n", line
);
182 for (i
= 0; i
< nf
; i
++)
183 if (strcmp(f
[i
], "\"\"") == 0)
189 try(f
[0], f
[1], f
[2], f
[3], f
[4], options('c', f
[1]));
190 if (opt('&', f
[1])) /* try with either type of RE */
191 try(f
[0], f
[1], f
[2], f
[3], f
[4],
192 options('c', f
[1]) &~ REG_EXTENDED
);
195 ne
= regerror(REG_BADPAT
, NULL
, erbuf
, sizeof(erbuf
));
196 if (strcmp(erbuf
, badpat
) != 0 || ne
!= strlen(badpat
)+1) {
197 fprintf(stderr
, "end: regerror() test gave `%s' not `%s'\n",
201 ne
= regerror(REG_BADPAT
, NULL
, erbuf
, (size_t)SHORT
);
202 if (strncmp(erbuf
, badpat
, SHORT
-1) != 0 || erbuf
[SHORT
-1] != '\0' ||
203 ne
!= strlen(badpat
)+1) {
204 fprintf(stderr
, "end: regerror() short test gave `%s' not `%.*s'\n",
205 erbuf
, SHORT
-1, badpat
);
208 ne
= regerror(REG_ITOA
|REG_BADPAT
, NULL
, erbuf
, sizeof(erbuf
));
209 if (strcmp(erbuf
, bpname
) != 0 || ne
!= strlen(bpname
)+1) {
210 fprintf(stderr
, "end: regerror() ITOA test gave `%s' not `%s'\n",
215 ne
= regerror(REG_ATOI
, &re
, erbuf
, sizeof(erbuf
));
216 if (atoi(erbuf
) != (int)REG_BADPAT
) {
217 fprintf(stderr
, "end: regerror() ATOI test gave `%s' not `%ld'\n",
218 erbuf
, (long)REG_BADPAT
);
220 } else if (ne
!= strlen(erbuf
)+1) {
221 fprintf(stderr
, "end: regerror() ATOI test len(`%s') = %ld\n",
222 erbuf
, (long)REG_BADPAT
);
228 - try - try it, and report on problems
229 == void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
232 try(char *f0
, char *f1
, char *f2
, char *f3
, char *f4
, int opts
)
236 regmatch_t subs
[NSUBS
];
238 char *should
[NSHOULD
];
243 const char *type
= (opts
& REG_EXTENDED
) ? "ERE" : "BRE";
250 re
.re_endp
= (opts
®_PEND
) ? f0copy
+ strlen(f0copy
) : NULL
;
252 err
= regcomp(&re
, f0copy
, opts
);
253 if (err
!= 0 && (!opt('C', f1
) || err
!= efind(f2
))) {
254 /* unexpected error or wrong error */
255 len
= regerror(err
, &re
, erbuf
, sizeof(erbuf
));
256 fprintf(stderr
, "%d: %s error %s, %d/%d `%s'\n",
257 line
, type
, eprint(err
), len
,
258 (int)sizeof(erbuf
), erbuf
);
260 } else if (err
== 0 && opt('C', f1
)) {
261 /* unexpected success */
262 fprintf(stderr
, "%d: %s should have given REG_%s\n",
265 err
= 1; /* so we won't try regexec */
276 if (options('e', f1
)®_STARTEND
) {
277 if (strchr(f2
, '(') == NULL
|| strchr(f2
, ')') == NULL
)
278 fprintf(stderr
, "%d: bad STARTEND syntax\n", line
);
279 subs
[0].rm_so
= strchr(f2
, '(') - f2
+ 1;
280 subs
[0].rm_eo
= strchr(f2
, ')') - f2
;
282 err
= regexec(&re
, f2copy
, NSUBS
, subs
, options('e', f1
));
284 if (err
!= 0 && (f3
!= NULL
|| err
!= REG_NOMATCH
)) {
285 /* unexpected error or wrong error */
286 len
= regerror(err
, &re
, erbuf
, sizeof(erbuf
));
287 fprintf(stderr
, "%d: %s exec error %s, %d/%d `%s'\n",
288 line
, type
, eprint(err
), len
,
289 (int)sizeof(erbuf
), erbuf
);
291 } else if (err
!= 0) {
292 /* nothing more to check */
293 } else if (f3
== NULL
) {
294 /* unexpected success */
295 fprintf(stderr
, "%d: %s exec should have failed\n",
298 err
= 1; /* just on principle */
299 } else if (opts
®_NOSUB
) {
300 /* nothing more to check */
301 } else if ((grump
= check(f2
, subs
[0], f3
)) != NULL
) {
302 fprintf(stderr
, "%d: %s %s\n", line
, type
, grump
);
307 if (err
!= 0 || f4
== NULL
) {
312 for (i
= 1; i
< NSHOULD
; i
++)
314 nshould
= split(f4
, &should
[1], NSHOULD
-1, ",");
319 for (i
= 1; i
< NSUBS
; i
++) {
320 grump
= check(f2
, subs
[i
], should
[i
]);
322 fprintf(stderr
, "%d: %s $%d %s\n", line
,
333 - options - pick options out of a regression-test string
334 == int options(int type, char *s);
337 options(int type
, char *s
)
340 int o
= (type
== 'c') ? copts
: eopts
;
341 const char *legal
= (type
== 'c') ? "bisnmp" : "^$#tl";
343 for (p
= s
; *p
!= '\0'; p
++)
344 if (strchr(legal
, *p
) != NULL
)
374 case 't': /* trace */
377 case 'l': /* force long representation */
380 case 'r': /* force backref use */
388 - opt - is a particular option in a regression string?
389 == int opt(int c, char *s);
394 return(strchr(s
, c
) != NULL
);
398 - fixstr - transform magic characters in strings
399 == void fixstr(char *p);
407 for (; *p
!= '\0'; p
++)
419 * check - check a substring match
421 char * /* NULL or complaint */
422 check(char *str
, regmatch_t sub
, char *should
)
427 static char grump
[500];
430 if (should
!= NULL
&& strcmp(should
, "-") == 0)
432 if (should
!= NULL
&& should
[0] == '@') {
437 /* check rm_so and rm_eo for consistency */
438 if (sub
.rm_so
> sub
.rm_eo
|| (sub
.rm_so
== -1 && sub
.rm_eo
!= -1) ||
439 (sub
.rm_so
!= -1 && sub
.rm_eo
== -1) ||
440 (sub
.rm_so
!= -1 && sub
.rm_so
< 0) ||
441 (sub
.rm_eo
!= -1 && sub
.rm_eo
< 0) ) {
442 sprintf(grump
, "start %ld end %ld", (long)sub
.rm_so
,
447 /* check for no match */
448 if (sub
.rm_so
== -1) {
452 sprintf(grump
, "did not match");
457 /* check for in range */
458 if (sub
.rm_eo
> (ssize_t
)strlen(str
)) {
459 sprintf(grump
, "start %ld end %ld, past end of string",
460 (long)sub
.rm_so
, (long)sub
.rm_eo
);
464 len
= (int)(sub
.rm_eo
- sub
.rm_so
);
467 /* check for not supposed to match */
468 if (should
== NULL
) {
469 sprintf(grump
, "matched `%.*s'", len
, p
);
473 /* check for wrong match */
474 shlen
= (int)strlen(should
);
475 if (len
!= shlen
|| strncmp(p
, should
, (size_t)shlen
) != 0) {
476 sprintf(grump
, "matched `%.*s' instead", len
, p
);
482 /* check null match in right place */
487 shlen
= 1; /* force check for end-of-string */
488 if (strncmp(p
, at
, shlen
) != 0) {
489 sprintf(grump
, "matched null at `%.20s'", p
);
496 * eprint - convert error number to name
501 static char epbuf
[100];
504 len
= regerror(REG_ITOA
|err
, NULL
, epbuf
, sizeof(epbuf
));
505 assert(len
<= sizeof(epbuf
));
510 * efind - convert error name to number
515 static char efbuf
[100];
518 sprintf(efbuf
, "REG_%s", name
);
519 assert(strlen(efbuf
) < sizeof(efbuf
));
521 (void) regerror(REG_ATOI
, &re
, efbuf
, sizeof(efbuf
));