1 /* $NetBSD: main.c,v 1.7 2006/05/23 21:52:55 jnemeth 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.
32 #include <sys/types.h>
43 int copts
= REG_EXTENDED
;
45 regoff_t startoff
= 0;
50 extern void regprint();
53 - main - do the simple case, hand off to regress() for regression
73 while ((c
= getopt(argc
, argv
, "c:e:S:E:x")) != -1)
75 case 'c': /* compile options */
76 copts
= options('c', optarg
);
78 case 'e': /* execute options */
79 eopts
= options('e', optarg
);
81 case 'S': /* start offset */
82 startoff
= (regoff_t
)atoi(optarg
);
84 case 'E': /* end offset */
85 endoff
= (regoff_t
)atoi(optarg
);
87 case 'x': /* Debugging. */
96 fprintf(stderr
, "usage: %s ", progname
);
97 fprintf(stderr
, "[-c copt][-C][-d] [re]\n");
101 if (optind
>= argc
) {
106 err
= regcomp(&re
, argv
[optind
++], copts
);
108 len
= regerror(err
, &re
, erbuf
, sizeof(erbuf
));
109 fprintf(stderr
, "error %s, %d/%d `%s'\n",
110 eprint(err
), len
, sizeof(erbuf
), erbuf
);
113 regprint(&re
, stdout
);
115 if (optind
>= argc
) {
120 if (eopts
®_STARTEND
) {
121 subs
[0].rm_so
= startoff
;
122 subs
[0].rm_eo
= strlen(argv
[optind
]) - endoff
;
124 err
= regexec(&re
, argv
[optind
], (size_t)NS
, subs
, eopts
);
126 len
= regerror(err
, &re
, erbuf
, sizeof(erbuf
));
127 fprintf(stderr
, "error %s, %d/%d `%s'\n",
128 eprint(err
), len
, sizeof(erbuf
), erbuf
);
131 if (!(copts
®_NOSUB
)) {
132 len
= (int)(subs
[0].rm_eo
- subs
[0].rm_so
);
133 if (subs
[0].rm_so
!= -1) {
135 printf("match `%.*s'\n", len
,
136 argv
[optind
] + subs
[0].rm_so
);
138 printf("match `'@%.1s\n",
139 argv
[optind
] + subs
[0].rm_so
);
141 for (i
= 1; i
< NS
; i
++)
142 if (subs
[i
].rm_so
!= -1)
143 printf("(%d) `%.*s'\n", i
,
144 (int)(subs
[i
].rm_eo
- subs
[i
].rm_so
),
145 argv
[optind
] + subs
[i
].rm_so
);
151 - regress - main loop of regression test
152 == void regress(FILE *in);
165 char *badpat
= "invalid regular expression";
167 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
, (regex_t
*)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
, (regex_t
*)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
, (regex_t
*)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(f0
, f1
, f2
, f3
, f4
, opts
)
238 int opts
; /* may not match f1 */
242 regmatch_t subs
[NSUBS
];
244 char *should
[NSHOULD
];
249 char *type
= (opts
& REG_EXTENDED
) ? "ERE" : "BRE";
256 re
.re_endp
= (opts
®_PEND
) ? f0copy
+ strlen(f0copy
) : NULL
;
258 err
= regcomp(&re
, f0copy
, opts
);
259 if (err
!= 0 && (!opt('C', f1
) || err
!= efind(f2
))) {
260 /* unexpected error or wrong error */
261 len
= regerror(err
, &re
, erbuf
, sizeof(erbuf
));
262 fprintf(stderr
, "%d: %s error %s, %d/%d `%s'\n",
263 line
, type
, eprint(err
), len
,
264 sizeof(erbuf
), erbuf
);
266 } else if (err
== 0 && opt('C', f1
)) {
267 /* unexpected success */
268 fprintf(stderr
, "%d: %s should have given REG_%s\n",
271 err
= 1; /* so we won't try regexec */
282 if (options('e', f1
)®_STARTEND
) {
283 if (strchr(f2
, '(') == NULL
|| strchr(f2
, ')') == NULL
)
284 fprintf(stderr
, "%d: bad STARTEND syntax\n", line
);
285 subs
[0].rm_so
= strchr(f2
, '(') - f2
+ 1;
286 subs
[0].rm_eo
= strchr(f2
, ')') - f2
;
288 err
= regexec(&re
, f2copy
, NSUBS
, subs
, options('e', f1
));
290 if (err
!= 0 && (f3
!= NULL
|| err
!= REG_NOMATCH
)) {
291 /* unexpected error or wrong error */
292 len
= regerror(err
, &re
, erbuf
, sizeof(erbuf
));
293 fprintf(stderr
, "%d: %s exec error %s, %d/%d `%s'\n",
294 line
, type
, eprint(err
), len
,
295 sizeof(erbuf
), erbuf
);
297 } else if (err
!= 0) {
298 /* nothing more to check */
299 } else if (f3
== NULL
) {
300 /* unexpected success */
301 fprintf(stderr
, "%d: %s exec should have failed\n",
304 err
= 1; /* just on principle */
305 } else if (opts
®_NOSUB
) {
306 /* nothing more to check */
307 } else if ((grump
= check(f2
, subs
[0], f3
)) != NULL
) {
308 fprintf(stderr
, "%d: %s %s\n", line
, type
, grump
);
313 if (err
!= 0 || f4
== NULL
) {
318 for (i
= 1; i
< NSHOULD
; i
++)
320 nshould
= split(f4
, should
+1, NSHOULD
-1, ",");
325 for (i
= 1; i
< NSUBS
; i
++) {
326 grump
= check(f2
, subs
[i
], should
[i
]);
328 fprintf(stderr
, "%d: %s $%d %s\n", line
,
339 - options - pick options out of a regression-test string
340 == int options(int type, char *s);
344 int type
; /* 'c' compile, 'e' exec */
348 int o
= (type
== 'c') ? copts
: eopts
;
349 char *legal
= (type
== 'c') ? "bisnmp" : "^$#tl";
351 for (p
= s
; *p
!= '\0'; p
++)
352 if (strchr(legal
, *p
) != NULL
)
382 case 't': /* trace */
385 case 'l': /* force long representation */
388 case 'r': /* force backref use */
396 - opt - is a particular option in a regression string?
397 == int opt(int c, char *s);
404 return(strchr(s
, c
) != NULL
);
408 - fixstr - transform magic characters in strings
409 == void fixstr(char *p);
418 for (; *p
!= '\0'; p
++)
430 - check - check a substring match
431 == char *check(char *str, regmatch_t sub, char *should);
433 char * /* NULL or complaint */
434 check(str
, sub
, should
)
442 static char grump
[500];
445 if (should
!= NULL
&& strcmp(should
, "-") == 0)
447 if (should
!= NULL
&& should
[0] == '@') {
452 /* check rm_so and rm_eo for consistency */
453 if (sub
.rm_so
> sub
.rm_eo
|| (sub
.rm_so
== -1 && sub
.rm_eo
!= -1) ||
454 (sub
.rm_so
!= -1 && sub
.rm_eo
== -1) ||
455 (sub
.rm_so
!= -1 && sub
.rm_so
< 0) ||
456 (sub
.rm_eo
!= -1 && sub
.rm_eo
< 0) ) {
457 sprintf(grump
, "start %ld end %ld", (long)sub
.rm_so
,
462 /* check for no match */
463 if (sub
.rm_so
== -1 && should
== NULL
)
466 return("did not match");
468 /* check for in range */
469 if (sub
.rm_eo
> strlen(str
)) {
470 sprintf(grump
, "start %ld end %ld, past end of string",
471 (long)sub
.rm_so
, (long)sub
.rm_eo
);
475 len
= (int)(sub
.rm_eo
- sub
.rm_so
);
478 /* check for not supposed to match */
479 if (should
== NULL
) {
480 sprintf(grump
, "matched `%.*s'", len
, p
);
484 /* check for wrong match */
485 shlen
= (int)strlen(should
);
486 if (len
!= shlen
|| strncmp(p
, should
, (size_t)shlen
) != 0) {
487 sprintf(grump
, "matched `%.*s' instead", len
, p
);
493 /* check null match in right place */
498 shlen
= 1; /* force check for end-of-string */
499 if (strncmp(p
, at
, shlen
) != 0) {
500 sprintf(grump
, "matched null at `%.20s'", p
);
507 - eprint - convert error number to name
508 == static char *eprint(int err);
514 static char epbuf
[100];
517 len
= regerror(REG_ITOA
|err
, (regex_t
*)NULL
, epbuf
, sizeof(epbuf
));
518 assert(len
<= sizeof(epbuf
));
523 - efind - convert error name to number
524 == static int efind(char *name);
530 static char efbuf
[100];
534 sprintf(efbuf
, "REG_%s", name
);
535 assert(strlen(efbuf
) < sizeof(efbuf
));
537 (void) regerror(REG_ATOI
, &re
, efbuf
, sizeof(efbuf
));