19 int copts = REG_EXTENDED;
21 regoff_t startoff = 0;
26 extern void regprint();
29 - main - do the simple case, hand off to regress() for regression
32 main(int argc, char **argv)
48 while ((c = getopt(argc, argv, "c:e:S:E:x")) != -1)
50 case 'c': /* compile options */
51 copts = options('c', optarg);
53 case 'e': /* execute options */
54 eopts = options('e', optarg);
56 case 'S': /* start offset */
57 startoff = (regoff_t)atoi(optarg);
59 case 'E': /* end offset */
60 endoff = (regoff_t)atoi(optarg);
62 case 'x': /* Debugging. */
71 fprintf(stderr, "usage: %s ", progname);
72 fprintf(stderr, "[-c copt][-C][-d] [re]\n");
81 err = regcomp(&re, argv[optind++], copts);
83 len = regerror(err, &re, erbuf, sizeof(erbuf));
84 fprintf(stderr, "error %s, %zu/%zu `%s'\n",
85 eprint(err), len, sizeof(erbuf), erbuf);
88 regprint(&re, stdout);
95 if ((eopts & REG_STARTEND) != 0) {
96 subs[0].rm_so = startoff;
97 subs[0].rm_eo = strlen(argv[optind]) - endoff;
99 err = regexec(&re, argv[optind], (size_t)NS, subs, eopts);
101 len = regerror(err, &re, erbuf, sizeof(erbuf));
102 fprintf(stderr, "error %s, %zu/%zu `%s'\n",
103 eprint(err), len, sizeof(erbuf), erbuf);
106 if ((copts & REG_NOSUB) == 0) {
107 len = (int)(subs[0].rm_eo - subs[0].rm_so);
108 if (subs[0].rm_so != -1) {
110 printf("match `%.*s'\n", (int)len,
111 argv[optind] + subs[0].rm_so);
113 printf("match `'@%.1s\n",
114 argv[optind] + subs[0].rm_so);
116 for (i = 1; i < NS; i++)
117 if (subs[i].rm_so != -1)
118 printf("(%d) `%.*s'\n", i,
119 (int)(subs[i].rm_eo - subs[i].rm_so),
120 argv[optind] + subs[i].rm_so);
126 - regress - main loop of regression test
127 == void regress(FILE *in);
139 char *badpat = "invalid regular expression";
141 char *bpname = "REG_BADPAT";
144 while (fgets(inbuf, sizeof(inbuf), in) != NULL) {
146 if (inbuf[0] == '#' || inbuf[0] == '\n')
147 continue; /* NOTE CONTINUE */
148 inbuf[strlen(inbuf)-1] = '\0'; /* get rid of stupid \n */
150 fprintf(stdout, "%d:\n", line);
151 nf = split(inbuf, f, MAXF, "\t\t");
153 fprintf(stderr, "bad input, line %d\n", line);
156 for (i = 0; i < nf; i++)
157 if (strcmp(f[i], "\"\"") == 0)
163 try(f[0], f[1], f[2], f[3], f[4], options('c', f[1]));
164 if (opt('&', f[1])) /* try with either type of RE */
165 try(f[0], f[1], f[2], f[3], f[4],
166 options('c', f[1]) &~ REG_EXTENDED);
169 ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf));
170 if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) {
171 fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n",
175 ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, (size_t)SHORT);
176 if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' ||
177 ne != strlen(badpat)+1) {
178 fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n",
179 erbuf, SHORT-1, badpat);
182 ne = regerror(REG_ITOA|REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf));
183 if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname) + 1) {
184 fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n",
189 ne = regerror(REG_ATOI, &re, erbuf, sizeof(erbuf));
190 if (atoi(erbuf) != (int)REG_BADPAT) {
191 fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n",
192 erbuf, (long)REG_BADPAT);
194 } else if (ne != strlen(erbuf) + 1) {
195 fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n",
196 erbuf, (long)REG_BADPAT);
202 - try - try it, and report on problems
203 == void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
204 - opts: may not match f1
207 try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts)
211 regmatch_t subs[NSUBS];
213 char *should[NSHOULD];
218 char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE";
223 re.re_endp = (opts®_PEND) ? f0copy + strlen(f0copy) : NULL;
225 err = regcomp(&re, f0copy, opts);
226 if (err != 0 && (!opt('C', f1) || err != efind(f2))) {
227 /* unexpected error or wrong error */
228 len = regerror(err, &re, erbuf, sizeof(erbuf));
229 fprintf(stderr, "%d: %s error %s, %zu/%zu `%s'\n",
230 line, type, eprint(err), len, sizeof(erbuf), erbuf);
232 } else if (err == 0 && opt('C', f1)) {
233 /* unexpected success */
234 fprintf(stderr, "%d: %s should have given REG_%s\n",
237 err = 1; /* so we won't try regexec */
248 if (options('e', f1)®_STARTEND) {
249 if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL)
250 fprintf(stderr, "%d: bad STARTEND syntax\n", line);
251 subs[0].rm_so = strchr(f2, '(') - f2 + 1;
252 subs[0].rm_eo = strchr(f2, ')') - f2;
254 err = regexec(&re, f2copy, NSUBS, subs, options('e', f1));
256 if (err != 0 && (f3 != NULL || err != REG_NOMATCH)) {
257 /* unexpected error or wrong error */
258 len = regerror(err, &re, erbuf, sizeof(erbuf));
259 fprintf(stderr, "%d: %s exec error %s, %zu/%zu `%s'\n",
260 line, type, eprint(err), len, sizeof(erbuf), erbuf);
262 } else if (err != 0) {
263 /* nothing more to check */
264 } else if (f3 == NULL) {
265 /* unexpected success */
266 fprintf(stderr, "%d: %s exec should have failed\n",
269 err = 1; /* just on principle */
270 } else if (opts®_NOSUB) {
271 /* nothing more to check */
272 } else if ((grump = check(f2, subs[0], f3)) != NULL) {
273 fprintf(stderr, "%d: %s %s\n", line, type, grump);
278 if (err != 0 || f4 == NULL) {
283 for (i = 1; i < NSHOULD; i++)
285 nshould = split(f4, should+1, NSHOULD-1, ",");
290 for (i = 1; i < NSUBS; i++) {
291 grump = check(f2, subs[i], should[i]);
293 fprintf(stderr, "%d: %s $%d %s\n", line,
304 - options - pick options out of a regression-test string
305 - type: 'c' - compile, 'e' - exec
306 == int options(int type, char *s);
309 options(int type, char *s)
312 int o = (type == 'c') ? copts : eopts;
313 char *legal = (type == 'c') ? "bisnmp" : "^$#tl";
315 for (p = s; *p != '\0'; p++)
316 if (strchr(legal, *p) != NULL)
346 case 't': /* trace */
349 case 'l': /* force long representation */
352 case 'r': /* force backref use */
360 - opt - is a particular option in a regression string?
361 == int opt(int c, char *s);
366 return(strchr(s, c) != NULL);
370 - fixstr - transform magic characters in strings
371 == void fixstr(char *p);
379 for (; *p != '\0'; p++)
391 - check - check a substring match
392 == char *check(char *str, regmatch_t sub, char *should);
394 char * /* NULL or complaint */
395 check(char *str, regmatch_t sub, char *should)
400 static char grump[500];
403 if (should != NULL && strcmp(should, "-") == 0)
405 if (should != NULL && should[0] == '@') {
410 /* check rm_so and rm_eo for consistency */
411 if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) ||
412 (sub.rm_so != -1 && sub.rm_eo == -1) ||
413 (sub.rm_so != -1 && sub.rm_so < 0) ||
414 (sub.rm_eo != -1 && sub.rm_eo < 0) ) {
415 sprintf(grump, "start %ld end %ld", (long)sub.rm_so,
420 /* check for no match */
421 if (sub.rm_so == -1 && should == NULL)
424 return("did not match");
426 /* check for in range */
427 if (sub.rm_eo > strlen(str)) {
428 sprintf(grump, "start %ld end %ld, past end of string",
429 (long)sub.rm_so, (long)sub.rm_eo);
433 len = (int)(sub.rm_eo - sub.rm_so);
434 shlen = (int)strlen(should);
437 /* check for not supposed to match */
438 if (should == NULL) {
439 sprintf(grump, "matched `%.*s'", len, p);
443 /* check for wrong match */
444 if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) {
445 sprintf(grump, "matched `%.*s' instead", len, p);
451 /* check null match in right place */
456 shlen = 1; /* force check for end-of-string */
457 if (strncmp(p, at, shlen) != 0) {
458 sprintf(grump, "matched null at `%.20s'", p);
465 - eprint - convert error number to name
466 == static char *eprint(int err);
471 static char epbuf[100];
474 len = regerror(REG_ITOA|err, (regex_t *)NULL, epbuf, sizeof(epbuf));
475 assert(len <= sizeof(epbuf));
480 - efind - convert error name to number
481 == static int efind(char *name);
486 static char efbuf[100];
490 sprintf(efbuf, "REG_%s", name);
491 assert(strlen(efbuf) < sizeof(efbuf));
493 (void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf));