157718be8SEnji Cooper /* $NetBSD: main.c,v 1.2 2011/09/16 16:13:18 plunky Exp $ */
257718be8SEnji Cooper
357718be8SEnji Cooper /*-
457718be8SEnji Cooper * Copyright (c) 1993 The NetBSD Foundation, Inc.
557718be8SEnji Cooper * All rights reserved.
657718be8SEnji Cooper *
757718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without
857718be8SEnji Cooper * modification, are permitted provided that the following conditions
957718be8SEnji Cooper * are met:
1057718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright
1157718be8SEnji Cooper * notice, this list of conditions and the following disclaimer.
1257718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright
1357718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the
1457718be8SEnji Cooper * documentation and/or other materials provided with the distribution.
1557718be8SEnji Cooper *
1657718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1757718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1857718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1957718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2057718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2157718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2257718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2357718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2457718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2557718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2657718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE.
2757718be8SEnji Cooper */
2857718be8SEnji Cooper
2957718be8SEnji Cooper #include <assert.h>
3057718be8SEnji Cooper #include <regex.h>
3157718be8SEnji Cooper #include <stdio.h>
3257718be8SEnji Cooper #include <stdlib.h>
3357718be8SEnji Cooper #include <string.h>
3457718be8SEnji Cooper #include <unistd.h>
3557718be8SEnji Cooper
3657718be8SEnji Cooper #include <sys/types.h>
3757718be8SEnji Cooper
3857718be8SEnji Cooper #include "test_regex.h"
3957718be8SEnji Cooper
4057718be8SEnji Cooper char *progname;
4157718be8SEnji Cooper int debug = 0;
4257718be8SEnji Cooper int line = 0;
4357718be8SEnji Cooper int status = 0;
4457718be8SEnji Cooper
4557718be8SEnji Cooper int copts = REG_EXTENDED;
4657718be8SEnji Cooper int eopts = 0;
4757718be8SEnji Cooper regoff_t startoff = 0;
4857718be8SEnji Cooper regoff_t endoff = 0;
4957718be8SEnji Cooper
5057718be8SEnji Cooper static char empty = '\0';
5157718be8SEnji Cooper
5257718be8SEnji Cooper static char *eprint(int);
5357718be8SEnji Cooper static int efind(char *);
5457718be8SEnji Cooper
5557718be8SEnji Cooper /*
5657718be8SEnji Cooper * main - do the simple case, hand off to regress() for regression
5757718be8SEnji Cooper */
5857718be8SEnji Cooper int
main(int argc,char * argv[])5957718be8SEnji Cooper main(int argc, char *argv[])
6057718be8SEnji Cooper {
6157718be8SEnji Cooper regex_t re;
6257718be8SEnji Cooper # define NS 10
6357718be8SEnji Cooper regmatch_t subs[NS];
6457718be8SEnji Cooper char erbuf[100];
6557718be8SEnji Cooper int err;
6657718be8SEnji Cooper size_t len;
6757718be8SEnji Cooper int c;
6857718be8SEnji Cooper int errflg = 0;
6957718be8SEnji Cooper int i;
7057718be8SEnji Cooper extern int optind;
7157718be8SEnji Cooper extern char *optarg;
7257718be8SEnji Cooper
7357718be8SEnji Cooper progname = argv[0];
7457718be8SEnji Cooper
7557718be8SEnji Cooper while ((c = getopt(argc, argv, "c:e:S:E:x")) != -1)
7657718be8SEnji Cooper switch (c) {
7757718be8SEnji Cooper case 'c': /* compile options */
7857718be8SEnji Cooper copts = options('c', optarg);
7957718be8SEnji Cooper break;
8057718be8SEnji Cooper case 'e': /* execute options */
8157718be8SEnji Cooper eopts = options('e', optarg);
8257718be8SEnji Cooper break;
8357718be8SEnji Cooper case 'S': /* start offset */
8457718be8SEnji Cooper startoff = (regoff_t)atoi(optarg);
8557718be8SEnji Cooper break;
8657718be8SEnji Cooper case 'E': /* end offset */
8757718be8SEnji Cooper endoff = (regoff_t)atoi(optarg);
8857718be8SEnji Cooper break;
8957718be8SEnji Cooper case 'x': /* Debugging. */
9057718be8SEnji Cooper debug++;
9157718be8SEnji Cooper break;
9257718be8SEnji Cooper case '?':
9357718be8SEnji Cooper default:
9457718be8SEnji Cooper errflg++;
9557718be8SEnji Cooper break;
9657718be8SEnji Cooper }
9757718be8SEnji Cooper if (errflg) {
9857718be8SEnji Cooper fprintf(stderr, "usage: %s ", progname);
9957718be8SEnji Cooper fprintf(stderr, "[-c copt][-C][-d] [re]\n");
10057718be8SEnji Cooper exit(2);
10157718be8SEnji Cooper }
10257718be8SEnji Cooper
10357718be8SEnji Cooper if (optind >= argc) {
10457718be8SEnji Cooper regress(stdin);
10557718be8SEnji Cooper exit(status);
10657718be8SEnji Cooper }
10757718be8SEnji Cooper
10857718be8SEnji Cooper err = regcomp(&re, argv[optind++], copts);
10957718be8SEnji Cooper if (err) {
11057718be8SEnji Cooper len = regerror(err, &re, erbuf, sizeof(erbuf));
11157718be8SEnji Cooper fprintf(stderr, "error %s, %zd/%zd `%s'\n",
11257718be8SEnji Cooper eprint(err), len, (size_t)sizeof(erbuf), erbuf);
11357718be8SEnji Cooper exit(status);
11457718be8SEnji Cooper }
11557718be8SEnji Cooper regprint(&re, stdout);
11657718be8SEnji Cooper
11757718be8SEnji Cooper if (optind >= argc) {
11857718be8SEnji Cooper regfree(&re);
11957718be8SEnji Cooper exit(status);
12057718be8SEnji Cooper }
12157718be8SEnji Cooper
12257718be8SEnji Cooper if (eopts®_STARTEND) {
12357718be8SEnji Cooper subs[0].rm_so = startoff;
12457718be8SEnji Cooper subs[0].rm_eo = strlen(argv[optind]) - endoff;
12557718be8SEnji Cooper }
12657718be8SEnji Cooper err = regexec(&re, argv[optind], (size_t)NS, subs, eopts);
12757718be8SEnji Cooper if (err) {
12857718be8SEnji Cooper len = regerror(err, &re, erbuf, sizeof(erbuf));
12957718be8SEnji Cooper fprintf(stderr, "error %s, %zd/%zd `%s'\n",
13057718be8SEnji Cooper eprint(err), len, (size_t)sizeof(erbuf), erbuf);
13157718be8SEnji Cooper exit(status);
13257718be8SEnji Cooper }
13357718be8SEnji Cooper if (!(copts®_NOSUB)) {
13457718be8SEnji Cooper len = (int)(subs[0].rm_eo - subs[0].rm_so);
13557718be8SEnji Cooper if (subs[0].rm_so != -1) {
13657718be8SEnji Cooper if (len != 0)
13757718be8SEnji Cooper printf("match `%.*s'\n", (int)len,
13857718be8SEnji Cooper argv[optind] + subs[0].rm_so);
13957718be8SEnji Cooper else
14057718be8SEnji Cooper printf("match `'@%.1s\n",
14157718be8SEnji Cooper argv[optind] + subs[0].rm_so);
14257718be8SEnji Cooper }
14357718be8SEnji Cooper for (i = 1; i < NS; i++)
14457718be8SEnji Cooper if (subs[i].rm_so != -1)
14557718be8SEnji Cooper printf("(%d) `%.*s'\n", i,
14657718be8SEnji Cooper (int)(subs[i].rm_eo - subs[i].rm_so),
14757718be8SEnji Cooper argv[optind] + subs[i].rm_so);
14857718be8SEnji Cooper }
14957718be8SEnji Cooper exit(status);
15057718be8SEnji Cooper }
15157718be8SEnji Cooper
15257718be8SEnji Cooper /*
15357718be8SEnji Cooper * regress - main loop of regression test
15457718be8SEnji Cooper */
15557718be8SEnji Cooper void
regress(FILE * in)15657718be8SEnji Cooper regress(FILE *in)
15757718be8SEnji Cooper {
15857718be8SEnji Cooper char inbuf[1000];
15957718be8SEnji Cooper # define MAXF 10
16057718be8SEnji Cooper char *f[MAXF];
16157718be8SEnji Cooper int nf;
16257718be8SEnji Cooper int i;
16357718be8SEnji Cooper char erbuf[100];
16457718be8SEnji Cooper size_t ne;
16557718be8SEnji Cooper const char *badpat = "invalid regular expression";
16657718be8SEnji Cooper # define SHORT 10
16757718be8SEnji Cooper const char *bpname = "REG_BADPAT";
16857718be8SEnji Cooper regex_t re;
16957718be8SEnji Cooper
17057718be8SEnji Cooper while (fgets(inbuf, sizeof(inbuf), in) != NULL) {
17157718be8SEnji Cooper line++;
17257718be8SEnji Cooper if (inbuf[0] == '#' || inbuf[0] == '\n')
17357718be8SEnji Cooper continue; /* NOTE CONTINUE */
17457718be8SEnji Cooper inbuf[strlen(inbuf)-1] = '\0'; /* get rid of stupid \n */
17557718be8SEnji Cooper if (debug)
17657718be8SEnji Cooper fprintf(stdout, "%d:\n", line);
17757718be8SEnji Cooper nf = split(inbuf, f, MAXF, "\t\t");
17857718be8SEnji Cooper if (nf < 3) {
17957718be8SEnji Cooper fprintf(stderr, "bad input, line %d\n", line);
18057718be8SEnji Cooper exit(1);
18157718be8SEnji Cooper }
18257718be8SEnji Cooper for (i = 0; i < nf; i++)
18357718be8SEnji Cooper if (strcmp(f[i], "\"\"") == 0)
18457718be8SEnji Cooper f[i] = ∅
18557718be8SEnji Cooper if (nf <= 3)
18657718be8SEnji Cooper f[3] = NULL;
18757718be8SEnji Cooper if (nf <= 4)
18857718be8SEnji Cooper f[4] = NULL;
18957718be8SEnji Cooper try(f[0], f[1], f[2], f[3], f[4], options('c', f[1]));
19057718be8SEnji Cooper if (opt('&', f[1])) /* try with either type of RE */
19157718be8SEnji Cooper try(f[0], f[1], f[2], f[3], f[4],
19257718be8SEnji Cooper options('c', f[1]) &~ REG_EXTENDED);
19357718be8SEnji Cooper }
19457718be8SEnji Cooper
19557718be8SEnji Cooper ne = regerror(REG_BADPAT, NULL, erbuf, sizeof(erbuf));
19657718be8SEnji Cooper if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) {
19757718be8SEnji Cooper fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n",
19857718be8SEnji Cooper erbuf, badpat);
19957718be8SEnji Cooper status = 1;
20057718be8SEnji Cooper }
20157718be8SEnji Cooper ne = regerror(REG_BADPAT, NULL, erbuf, (size_t)SHORT);
20257718be8SEnji Cooper if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' ||
20357718be8SEnji Cooper ne != strlen(badpat)+1) {
20457718be8SEnji Cooper fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n",
20557718be8SEnji Cooper erbuf, SHORT-1, badpat);
20657718be8SEnji Cooper status = 1;
20757718be8SEnji Cooper }
20857718be8SEnji Cooper ne = regerror(REG_ITOA|REG_BADPAT, NULL, erbuf, sizeof(erbuf));
20957718be8SEnji Cooper if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname)+1) {
21057718be8SEnji Cooper fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n",
21157718be8SEnji Cooper erbuf, bpname);
21257718be8SEnji Cooper status = 1;
21357718be8SEnji Cooper }
21457718be8SEnji Cooper re.re_endp = bpname;
21557718be8SEnji Cooper ne = regerror(REG_ATOI, &re, erbuf, sizeof(erbuf));
21657718be8SEnji Cooper if (atoi(erbuf) != (int)REG_BADPAT) {
21757718be8SEnji Cooper fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n",
21857718be8SEnji Cooper erbuf, (long)REG_BADPAT);
21957718be8SEnji Cooper status = 1;
22057718be8SEnji Cooper } else if (ne != strlen(erbuf)+1) {
22157718be8SEnji Cooper fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n",
22257718be8SEnji Cooper erbuf, (long)REG_BADPAT);
22357718be8SEnji Cooper status = 1;
22457718be8SEnji Cooper }
22557718be8SEnji Cooper }
22657718be8SEnji Cooper
22757718be8SEnji Cooper /*
22857718be8SEnji Cooper - try - try it, and report on problems
22957718be8SEnji Cooper == void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
23057718be8SEnji Cooper */
23157718be8SEnji Cooper void
try(char * f0,char * f1,char * f2,char * f3,char * f4,int opts)23257718be8SEnji Cooper try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts)
23357718be8SEnji Cooper {
23457718be8SEnji Cooper regex_t re;
23557718be8SEnji Cooper # define NSUBS 10
23657718be8SEnji Cooper regmatch_t subs[NSUBS];
23757718be8SEnji Cooper # define NSHOULD 15
23857718be8SEnji Cooper char *should[NSHOULD];
23957718be8SEnji Cooper int nshould;
24057718be8SEnji Cooper char erbuf[100];
24157718be8SEnji Cooper int err;
24257718be8SEnji Cooper int len;
24357718be8SEnji Cooper const char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE";
24457718be8SEnji Cooper int i;
24557718be8SEnji Cooper char *grump;
24657718be8SEnji Cooper char f0copy[1000];
24757718be8SEnji Cooper char f2copy[1000];
24857718be8SEnji Cooper
24957718be8SEnji Cooper strcpy(f0copy, f0);
25057718be8SEnji Cooper re.re_endp = (opts®_PEND) ? f0copy + strlen(f0copy) : NULL;
25157718be8SEnji Cooper fixstr(f0copy);
25257718be8SEnji Cooper err = regcomp(&re, f0copy, opts);
25357718be8SEnji Cooper if (err != 0 && (!opt('C', f1) || err != efind(f2))) {
25457718be8SEnji Cooper /* unexpected error or wrong error */
25557718be8SEnji Cooper len = regerror(err, &re, erbuf, sizeof(erbuf));
25657718be8SEnji Cooper fprintf(stderr, "%d: %s error %s, %d/%d `%s'\n",
25757718be8SEnji Cooper line, type, eprint(err), len,
25857718be8SEnji Cooper (int)sizeof(erbuf), erbuf);
25957718be8SEnji Cooper status = 1;
26057718be8SEnji Cooper } else if (err == 0 && opt('C', f1)) {
26157718be8SEnji Cooper /* unexpected success */
26257718be8SEnji Cooper fprintf(stderr, "%d: %s should have given REG_%s\n",
26357718be8SEnji Cooper line, type, f2);
26457718be8SEnji Cooper status = 1;
26557718be8SEnji Cooper err = 1; /* so we won't try regexec */
26657718be8SEnji Cooper }
26757718be8SEnji Cooper
26857718be8SEnji Cooper if (err != 0) {
26957718be8SEnji Cooper regfree(&re);
27057718be8SEnji Cooper return;
27157718be8SEnji Cooper }
27257718be8SEnji Cooper
27357718be8SEnji Cooper strcpy(f2copy, f2);
27457718be8SEnji Cooper fixstr(f2copy);
27557718be8SEnji Cooper
27657718be8SEnji Cooper if (options('e', f1)®_STARTEND) {
27757718be8SEnji Cooper if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL)
27857718be8SEnji Cooper fprintf(stderr, "%d: bad STARTEND syntax\n", line);
27957718be8SEnji Cooper subs[0].rm_so = strchr(f2, '(') - f2 + 1;
28057718be8SEnji Cooper subs[0].rm_eo = strchr(f2, ')') - f2;
28157718be8SEnji Cooper }
28257718be8SEnji Cooper err = regexec(&re, f2copy, NSUBS, subs, options('e', f1));
28357718be8SEnji Cooper
28457718be8SEnji Cooper if (err != 0 && (f3 != NULL || err != REG_NOMATCH)) {
28557718be8SEnji Cooper /* unexpected error or wrong error */
28657718be8SEnji Cooper len = regerror(err, &re, erbuf, sizeof(erbuf));
28757718be8SEnji Cooper fprintf(stderr, "%d: %s exec error %s, %d/%d `%s'\n",
28857718be8SEnji Cooper line, type, eprint(err), len,
28957718be8SEnji Cooper (int)sizeof(erbuf), erbuf);
29057718be8SEnji Cooper status = 1;
29157718be8SEnji Cooper } else if (err != 0) {
29257718be8SEnji Cooper /* nothing more to check */
29357718be8SEnji Cooper } else if (f3 == NULL) {
29457718be8SEnji Cooper /* unexpected success */
29557718be8SEnji Cooper fprintf(stderr, "%d: %s exec should have failed\n",
29657718be8SEnji Cooper line, type);
29757718be8SEnji Cooper status = 1;
29857718be8SEnji Cooper err = 1; /* just on principle */
29957718be8SEnji Cooper } else if (opts®_NOSUB) {
30057718be8SEnji Cooper /* nothing more to check */
30157718be8SEnji Cooper } else if ((grump = check(f2, subs[0], f3)) != NULL) {
30257718be8SEnji Cooper fprintf(stderr, "%d: %s %s\n", line, type, grump);
30357718be8SEnji Cooper status = 1;
30457718be8SEnji Cooper err = 1;
30557718be8SEnji Cooper }
30657718be8SEnji Cooper
30757718be8SEnji Cooper if (err != 0 || f4 == NULL) {
30857718be8SEnji Cooper regfree(&re);
30957718be8SEnji Cooper return;
31057718be8SEnji Cooper }
31157718be8SEnji Cooper
31257718be8SEnji Cooper for (i = 1; i < NSHOULD; i++)
31357718be8SEnji Cooper should[i] = NULL;
31457718be8SEnji Cooper nshould = split(f4, &should[1], NSHOULD-1, ",");
31557718be8SEnji Cooper if (nshould == 0) {
31657718be8SEnji Cooper nshould = 1;
31757718be8SEnji Cooper should[1] = ∅
31857718be8SEnji Cooper }
31957718be8SEnji Cooper for (i = 1; i < NSUBS; i++) {
32057718be8SEnji Cooper grump = check(f2, subs[i], should[i]);
32157718be8SEnji Cooper if (grump != NULL) {
32257718be8SEnji Cooper fprintf(stderr, "%d: %s $%d %s\n", line,
32357718be8SEnji Cooper type, i, grump);
32457718be8SEnji Cooper status = 1;
32557718be8SEnji Cooper err = 1;
32657718be8SEnji Cooper }
32757718be8SEnji Cooper }
32857718be8SEnji Cooper
32957718be8SEnji Cooper regfree(&re);
33057718be8SEnji Cooper }
33157718be8SEnji Cooper
33257718be8SEnji Cooper /*
33357718be8SEnji Cooper - options - pick options out of a regression-test string
33457718be8SEnji Cooper == int options(int type, char *s);
33557718be8SEnji Cooper */
33657718be8SEnji Cooper int
options(int type,char * s)33757718be8SEnji Cooper options(int type, char *s)
33857718be8SEnji Cooper {
33957718be8SEnji Cooper char *p;
34057718be8SEnji Cooper int o = (type == 'c') ? copts : eopts;
341*4f1efa30SKyle Evans const char *legal = (type == 'c') ? "bisnmpP" : "^$#tl";
34257718be8SEnji Cooper
34357718be8SEnji Cooper for (p = s; *p != '\0'; p++)
34457718be8SEnji Cooper if (strchr(legal, *p) != NULL)
34557718be8SEnji Cooper switch (*p) {
34657718be8SEnji Cooper case 'b':
34757718be8SEnji Cooper o &= ~REG_EXTENDED;
34857718be8SEnji Cooper break;
34957718be8SEnji Cooper case 'i':
35057718be8SEnji Cooper o |= REG_ICASE;
35157718be8SEnji Cooper break;
35257718be8SEnji Cooper case 's':
35357718be8SEnji Cooper o |= REG_NOSUB;
35457718be8SEnji Cooper break;
35557718be8SEnji Cooper case 'n':
35657718be8SEnji Cooper o |= REG_NEWLINE;
35757718be8SEnji Cooper break;
35857718be8SEnji Cooper case 'm':
35957718be8SEnji Cooper o &= ~REG_EXTENDED;
36057718be8SEnji Cooper o |= REG_NOSPEC;
36157718be8SEnji Cooper break;
36257718be8SEnji Cooper case 'p':
36357718be8SEnji Cooper o |= REG_PEND;
36457718be8SEnji Cooper break;
365*4f1efa30SKyle Evans case 'P':
366*4f1efa30SKyle Evans o |= REG_POSIX;
367*4f1efa30SKyle Evans break;
36857718be8SEnji Cooper case '^':
36957718be8SEnji Cooper o |= REG_NOTBOL;
37057718be8SEnji Cooper break;
37157718be8SEnji Cooper case '$':
37257718be8SEnji Cooper o |= REG_NOTEOL;
37357718be8SEnji Cooper break;
37457718be8SEnji Cooper case '#':
37557718be8SEnji Cooper o |= REG_STARTEND;
37657718be8SEnji Cooper break;
37757718be8SEnji Cooper case 't': /* trace */
37857718be8SEnji Cooper o |= REG_TRACE;
37957718be8SEnji Cooper break;
38057718be8SEnji Cooper case 'l': /* force long representation */
38157718be8SEnji Cooper o |= REG_LARGE;
38257718be8SEnji Cooper break;
38357718be8SEnji Cooper case 'r': /* force backref use */
38457718be8SEnji Cooper o |= REG_BACKR;
38557718be8SEnji Cooper break;
38657718be8SEnji Cooper }
38757718be8SEnji Cooper return(o);
38857718be8SEnji Cooper }
38957718be8SEnji Cooper
39057718be8SEnji Cooper /*
39157718be8SEnji Cooper - opt - is a particular option in a regression string?
39257718be8SEnji Cooper == int opt(int c, char *s);
39357718be8SEnji Cooper */
39457718be8SEnji Cooper int /* predicate */
opt(int c,char * s)39557718be8SEnji Cooper opt(int c, char *s)
39657718be8SEnji Cooper {
39757718be8SEnji Cooper return(strchr(s, c) != NULL);
39857718be8SEnji Cooper }
39957718be8SEnji Cooper
40057718be8SEnji Cooper /*
40157718be8SEnji Cooper - fixstr - transform magic characters in strings
40257718be8SEnji Cooper == void fixstr(char *p);
40357718be8SEnji Cooper */
40457718be8SEnji Cooper void
fixstr(char * p)40557718be8SEnji Cooper fixstr(char *p)
40657718be8SEnji Cooper {
40757718be8SEnji Cooper if (p == NULL)
40857718be8SEnji Cooper return;
40957718be8SEnji Cooper
41057718be8SEnji Cooper for (; *p != '\0'; p++)
41157718be8SEnji Cooper if (*p == 'N')
41257718be8SEnji Cooper *p = '\n';
41357718be8SEnji Cooper else if (*p == 'T')
41457718be8SEnji Cooper *p = '\t';
41557718be8SEnji Cooper else if (*p == 'S')
41657718be8SEnji Cooper *p = ' ';
41757718be8SEnji Cooper else if (*p == 'Z')
41857718be8SEnji Cooper *p = '\0';
41957718be8SEnji Cooper }
42057718be8SEnji Cooper
42157718be8SEnji Cooper /*
42257718be8SEnji Cooper * check - check a substring match
42357718be8SEnji Cooper */
42457718be8SEnji Cooper char * /* NULL or complaint */
check(char * str,regmatch_t sub,char * should)42557718be8SEnji Cooper check(char *str, regmatch_t sub, char *should)
42657718be8SEnji Cooper {
42757718be8SEnji Cooper int len;
42857718be8SEnji Cooper int shlen;
42957718be8SEnji Cooper char *p;
43057718be8SEnji Cooper static char grump[500];
43157718be8SEnji Cooper char *at = NULL;
43257718be8SEnji Cooper
43357718be8SEnji Cooper if (should != NULL && strcmp(should, "-") == 0)
43457718be8SEnji Cooper should = NULL;
43557718be8SEnji Cooper if (should != NULL && should[0] == '@') {
43657718be8SEnji Cooper at = should + 1;
43757718be8SEnji Cooper should = ∅
43857718be8SEnji Cooper }
43957718be8SEnji Cooper
44057718be8SEnji Cooper /* check rm_so and rm_eo for consistency */
44157718be8SEnji Cooper if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) ||
44257718be8SEnji Cooper (sub.rm_so != -1 && sub.rm_eo == -1) ||
44357718be8SEnji Cooper (sub.rm_so != -1 && sub.rm_so < 0) ||
44457718be8SEnji Cooper (sub.rm_eo != -1 && sub.rm_eo < 0) ) {
44557718be8SEnji Cooper sprintf(grump, "start %ld end %ld", (long)sub.rm_so,
44657718be8SEnji Cooper (long)sub.rm_eo);
44757718be8SEnji Cooper return(grump);
44857718be8SEnji Cooper }
44957718be8SEnji Cooper
45057718be8SEnji Cooper /* check for no match */
45157718be8SEnji Cooper if (sub.rm_so == -1) {
45257718be8SEnji Cooper if (should == NULL)
45357718be8SEnji Cooper return(NULL);
45457718be8SEnji Cooper else {
45557718be8SEnji Cooper sprintf(grump, "did not match");
45657718be8SEnji Cooper return(grump);
45757718be8SEnji Cooper }
45857718be8SEnji Cooper }
45957718be8SEnji Cooper
46057718be8SEnji Cooper /* check for in range */
46157718be8SEnji Cooper if (sub.rm_eo > (ssize_t)strlen(str)) {
46257718be8SEnji Cooper sprintf(grump, "start %ld end %ld, past end of string",
46357718be8SEnji Cooper (long)sub.rm_so, (long)sub.rm_eo);
46457718be8SEnji Cooper return(grump);
46557718be8SEnji Cooper }
46657718be8SEnji Cooper
46757718be8SEnji Cooper len = (int)(sub.rm_eo - sub.rm_so);
46857718be8SEnji Cooper p = str + sub.rm_so;
46957718be8SEnji Cooper
47057718be8SEnji Cooper /* check for not supposed to match */
47157718be8SEnji Cooper if (should == NULL) {
47257718be8SEnji Cooper sprintf(grump, "matched `%.*s'", len, p);
47357718be8SEnji Cooper return(grump);
47457718be8SEnji Cooper }
47557718be8SEnji Cooper
47657718be8SEnji Cooper /* check for wrong match */
47757718be8SEnji Cooper shlen = (int)strlen(should);
47857718be8SEnji Cooper if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) {
47957718be8SEnji Cooper sprintf(grump, "matched `%.*s' instead", len, p);
48057718be8SEnji Cooper return(grump);
48157718be8SEnji Cooper }
48257718be8SEnji Cooper if (shlen > 0)
48357718be8SEnji Cooper return(NULL);
48457718be8SEnji Cooper
48557718be8SEnji Cooper /* check null match in right place */
48657718be8SEnji Cooper if (at == NULL)
48757718be8SEnji Cooper return(NULL);
48857718be8SEnji Cooper shlen = strlen(at);
48957718be8SEnji Cooper if (shlen == 0)
49057718be8SEnji Cooper shlen = 1; /* force check for end-of-string */
49157718be8SEnji Cooper if (strncmp(p, at, shlen) != 0) {
49257718be8SEnji Cooper sprintf(grump, "matched null at `%.20s'", p);
49357718be8SEnji Cooper return(grump);
49457718be8SEnji Cooper }
49557718be8SEnji Cooper return(NULL);
49657718be8SEnji Cooper }
49757718be8SEnji Cooper
49857718be8SEnji Cooper /*
49957718be8SEnji Cooper * eprint - convert error number to name
50057718be8SEnji Cooper */
50157718be8SEnji Cooper static char *
eprint(int err)50257718be8SEnji Cooper eprint(int err)
50357718be8SEnji Cooper {
50457718be8SEnji Cooper static char epbuf[100];
50557718be8SEnji Cooper size_t len;
50657718be8SEnji Cooper
50757718be8SEnji Cooper len = regerror(REG_ITOA|err, NULL, epbuf, sizeof(epbuf));
50857718be8SEnji Cooper assert(len <= sizeof(epbuf));
50957718be8SEnji Cooper return(epbuf);
51057718be8SEnji Cooper }
51157718be8SEnji Cooper
51257718be8SEnji Cooper /*
51357718be8SEnji Cooper * efind - convert error name to number
51457718be8SEnji Cooper */
51557718be8SEnji Cooper static int
efind(char * name)51657718be8SEnji Cooper efind(char *name)
51757718be8SEnji Cooper {
51857718be8SEnji Cooper static char efbuf[100];
51957718be8SEnji Cooper regex_t re;
52057718be8SEnji Cooper
52157718be8SEnji Cooper sprintf(efbuf, "REG_%s", name);
52257718be8SEnji Cooper assert(strlen(efbuf) < sizeof(efbuf));
52357718be8SEnji Cooper re.re_endp = efbuf;
52457718be8SEnji Cooper (void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf));
52557718be8SEnji Cooper return(atoi(efbuf));
52657718be8SEnji Cooper }
527