1*57718be8SEnji Cooper /* $NetBSD: main.c,v 1.2 2011/09/16 16:13:18 plunky Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /*- 4*57718be8SEnji Cooper * Copyright (c) 1993 The NetBSD Foundation, Inc. 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 8*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 9*57718be8SEnji Cooper * are met: 10*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 11*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 12*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 13*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 14*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 15*57718be8SEnji Cooper * 16*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18*57718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19*57718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20*57718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21*57718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22*57718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23*57718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24*57718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25*57718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26*57718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 27*57718be8SEnji Cooper */ 28*57718be8SEnji Cooper 29*57718be8SEnji Cooper #include <assert.h> 30*57718be8SEnji Cooper #include <regex.h> 31*57718be8SEnji Cooper #include <stdio.h> 32*57718be8SEnji Cooper #include <stdlib.h> 33*57718be8SEnji Cooper #include <string.h> 34*57718be8SEnji Cooper #include <unistd.h> 35*57718be8SEnji Cooper 36*57718be8SEnji Cooper #include <sys/types.h> 37*57718be8SEnji Cooper 38*57718be8SEnji Cooper #include "test_regex.h" 39*57718be8SEnji Cooper 40*57718be8SEnji Cooper char *progname; 41*57718be8SEnji Cooper int debug = 0; 42*57718be8SEnji Cooper int line = 0; 43*57718be8SEnji Cooper int status = 0; 44*57718be8SEnji Cooper 45*57718be8SEnji Cooper int copts = REG_EXTENDED; 46*57718be8SEnji Cooper int eopts = 0; 47*57718be8SEnji Cooper regoff_t startoff = 0; 48*57718be8SEnji Cooper regoff_t endoff = 0; 49*57718be8SEnji Cooper 50*57718be8SEnji Cooper static char empty = '\0'; 51*57718be8SEnji Cooper 52*57718be8SEnji Cooper static char *eprint(int); 53*57718be8SEnji Cooper static int efind(char *); 54*57718be8SEnji Cooper 55*57718be8SEnji Cooper /* 56*57718be8SEnji Cooper * main - do the simple case, hand off to regress() for regression 57*57718be8SEnji Cooper */ 58*57718be8SEnji Cooper int 59*57718be8SEnji Cooper main(int argc, char *argv[]) 60*57718be8SEnji Cooper { 61*57718be8SEnji Cooper regex_t re; 62*57718be8SEnji Cooper # define NS 10 63*57718be8SEnji Cooper regmatch_t subs[NS]; 64*57718be8SEnji Cooper char erbuf[100]; 65*57718be8SEnji Cooper int err; 66*57718be8SEnji Cooper size_t len; 67*57718be8SEnji Cooper int c; 68*57718be8SEnji Cooper int errflg = 0; 69*57718be8SEnji Cooper int i; 70*57718be8SEnji Cooper extern int optind; 71*57718be8SEnji Cooper extern char *optarg; 72*57718be8SEnji Cooper 73*57718be8SEnji Cooper progname = argv[0]; 74*57718be8SEnji Cooper 75*57718be8SEnji Cooper while ((c = getopt(argc, argv, "c:e:S:E:x")) != -1) 76*57718be8SEnji Cooper switch (c) { 77*57718be8SEnji Cooper case 'c': /* compile options */ 78*57718be8SEnji Cooper copts = options('c', optarg); 79*57718be8SEnji Cooper break; 80*57718be8SEnji Cooper case 'e': /* execute options */ 81*57718be8SEnji Cooper eopts = options('e', optarg); 82*57718be8SEnji Cooper break; 83*57718be8SEnji Cooper case 'S': /* start offset */ 84*57718be8SEnji Cooper startoff = (regoff_t)atoi(optarg); 85*57718be8SEnji Cooper break; 86*57718be8SEnji Cooper case 'E': /* end offset */ 87*57718be8SEnji Cooper endoff = (regoff_t)atoi(optarg); 88*57718be8SEnji Cooper break; 89*57718be8SEnji Cooper case 'x': /* Debugging. */ 90*57718be8SEnji Cooper debug++; 91*57718be8SEnji Cooper break; 92*57718be8SEnji Cooper case '?': 93*57718be8SEnji Cooper default: 94*57718be8SEnji Cooper errflg++; 95*57718be8SEnji Cooper break; 96*57718be8SEnji Cooper } 97*57718be8SEnji Cooper if (errflg) { 98*57718be8SEnji Cooper fprintf(stderr, "usage: %s ", progname); 99*57718be8SEnji Cooper fprintf(stderr, "[-c copt][-C][-d] [re]\n"); 100*57718be8SEnji Cooper exit(2); 101*57718be8SEnji Cooper } 102*57718be8SEnji Cooper 103*57718be8SEnji Cooper if (optind >= argc) { 104*57718be8SEnji Cooper regress(stdin); 105*57718be8SEnji Cooper exit(status); 106*57718be8SEnji Cooper } 107*57718be8SEnji Cooper 108*57718be8SEnji Cooper err = regcomp(&re, argv[optind++], copts); 109*57718be8SEnji Cooper if (err) { 110*57718be8SEnji Cooper len = regerror(err, &re, erbuf, sizeof(erbuf)); 111*57718be8SEnji Cooper fprintf(stderr, "error %s, %zd/%zd `%s'\n", 112*57718be8SEnji Cooper eprint(err), len, (size_t)sizeof(erbuf), erbuf); 113*57718be8SEnji Cooper exit(status); 114*57718be8SEnji Cooper } 115*57718be8SEnji Cooper regprint(&re, stdout); 116*57718be8SEnji Cooper 117*57718be8SEnji Cooper if (optind >= argc) { 118*57718be8SEnji Cooper regfree(&re); 119*57718be8SEnji Cooper exit(status); 120*57718be8SEnji Cooper } 121*57718be8SEnji Cooper 122*57718be8SEnji Cooper if (eopts®_STARTEND) { 123*57718be8SEnji Cooper subs[0].rm_so = startoff; 124*57718be8SEnji Cooper subs[0].rm_eo = strlen(argv[optind]) - endoff; 125*57718be8SEnji Cooper } 126*57718be8SEnji Cooper err = regexec(&re, argv[optind], (size_t)NS, subs, eopts); 127*57718be8SEnji Cooper if (err) { 128*57718be8SEnji Cooper len = regerror(err, &re, erbuf, sizeof(erbuf)); 129*57718be8SEnji Cooper fprintf(stderr, "error %s, %zd/%zd `%s'\n", 130*57718be8SEnji Cooper eprint(err), len, (size_t)sizeof(erbuf), erbuf); 131*57718be8SEnji Cooper exit(status); 132*57718be8SEnji Cooper } 133*57718be8SEnji Cooper if (!(copts®_NOSUB)) { 134*57718be8SEnji Cooper len = (int)(subs[0].rm_eo - subs[0].rm_so); 135*57718be8SEnji Cooper if (subs[0].rm_so != -1) { 136*57718be8SEnji Cooper if (len != 0) 137*57718be8SEnji Cooper printf("match `%.*s'\n", (int)len, 138*57718be8SEnji Cooper argv[optind] + subs[0].rm_so); 139*57718be8SEnji Cooper else 140*57718be8SEnji Cooper printf("match `'@%.1s\n", 141*57718be8SEnji Cooper argv[optind] + subs[0].rm_so); 142*57718be8SEnji Cooper } 143*57718be8SEnji Cooper for (i = 1; i < NS; i++) 144*57718be8SEnji Cooper if (subs[i].rm_so != -1) 145*57718be8SEnji Cooper printf("(%d) `%.*s'\n", i, 146*57718be8SEnji Cooper (int)(subs[i].rm_eo - subs[i].rm_so), 147*57718be8SEnji Cooper argv[optind] + subs[i].rm_so); 148*57718be8SEnji Cooper } 149*57718be8SEnji Cooper exit(status); 150*57718be8SEnji Cooper } 151*57718be8SEnji Cooper 152*57718be8SEnji Cooper /* 153*57718be8SEnji Cooper * regress - main loop of regression test 154*57718be8SEnji Cooper */ 155*57718be8SEnji Cooper void 156*57718be8SEnji Cooper regress(FILE *in) 157*57718be8SEnji Cooper { 158*57718be8SEnji Cooper char inbuf[1000]; 159*57718be8SEnji Cooper # define MAXF 10 160*57718be8SEnji Cooper char *f[MAXF]; 161*57718be8SEnji Cooper int nf; 162*57718be8SEnji Cooper int i; 163*57718be8SEnji Cooper char erbuf[100]; 164*57718be8SEnji Cooper size_t ne; 165*57718be8SEnji Cooper const char *badpat = "invalid regular expression"; 166*57718be8SEnji Cooper # define SHORT 10 167*57718be8SEnji Cooper const char *bpname = "REG_BADPAT"; 168*57718be8SEnji Cooper regex_t re; 169*57718be8SEnji Cooper 170*57718be8SEnji Cooper while (fgets(inbuf, sizeof(inbuf), in) != NULL) { 171*57718be8SEnji Cooper line++; 172*57718be8SEnji Cooper if (inbuf[0] == '#' || inbuf[0] == '\n') 173*57718be8SEnji Cooper continue; /* NOTE CONTINUE */ 174*57718be8SEnji Cooper inbuf[strlen(inbuf)-1] = '\0'; /* get rid of stupid \n */ 175*57718be8SEnji Cooper if (debug) 176*57718be8SEnji Cooper fprintf(stdout, "%d:\n", line); 177*57718be8SEnji Cooper nf = split(inbuf, f, MAXF, "\t\t"); 178*57718be8SEnji Cooper if (nf < 3) { 179*57718be8SEnji Cooper fprintf(stderr, "bad input, line %d\n", line); 180*57718be8SEnji Cooper exit(1); 181*57718be8SEnji Cooper } 182*57718be8SEnji Cooper for (i = 0; i < nf; i++) 183*57718be8SEnji Cooper if (strcmp(f[i], "\"\"") == 0) 184*57718be8SEnji Cooper f[i] = ∅ 185*57718be8SEnji Cooper if (nf <= 3) 186*57718be8SEnji Cooper f[3] = NULL; 187*57718be8SEnji Cooper if (nf <= 4) 188*57718be8SEnji Cooper f[4] = NULL; 189*57718be8SEnji Cooper try(f[0], f[1], f[2], f[3], f[4], options('c', f[1])); 190*57718be8SEnji Cooper if (opt('&', f[1])) /* try with either type of RE */ 191*57718be8SEnji Cooper try(f[0], f[1], f[2], f[3], f[4], 192*57718be8SEnji Cooper options('c', f[1]) &~ REG_EXTENDED); 193*57718be8SEnji Cooper } 194*57718be8SEnji Cooper 195*57718be8SEnji Cooper ne = regerror(REG_BADPAT, NULL, erbuf, sizeof(erbuf)); 196*57718be8SEnji Cooper if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) { 197*57718be8SEnji Cooper fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n", 198*57718be8SEnji Cooper erbuf, badpat); 199*57718be8SEnji Cooper status = 1; 200*57718be8SEnji Cooper } 201*57718be8SEnji Cooper ne = regerror(REG_BADPAT, NULL, erbuf, (size_t)SHORT); 202*57718be8SEnji Cooper if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' || 203*57718be8SEnji Cooper ne != strlen(badpat)+1) { 204*57718be8SEnji Cooper fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n", 205*57718be8SEnji Cooper erbuf, SHORT-1, badpat); 206*57718be8SEnji Cooper status = 1; 207*57718be8SEnji Cooper } 208*57718be8SEnji Cooper ne = regerror(REG_ITOA|REG_BADPAT, NULL, erbuf, sizeof(erbuf)); 209*57718be8SEnji Cooper if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname)+1) { 210*57718be8SEnji Cooper fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n", 211*57718be8SEnji Cooper erbuf, bpname); 212*57718be8SEnji Cooper status = 1; 213*57718be8SEnji Cooper } 214*57718be8SEnji Cooper re.re_endp = bpname; 215*57718be8SEnji Cooper ne = regerror(REG_ATOI, &re, erbuf, sizeof(erbuf)); 216*57718be8SEnji Cooper if (atoi(erbuf) != (int)REG_BADPAT) { 217*57718be8SEnji Cooper fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n", 218*57718be8SEnji Cooper erbuf, (long)REG_BADPAT); 219*57718be8SEnji Cooper status = 1; 220*57718be8SEnji Cooper } else if (ne != strlen(erbuf)+1) { 221*57718be8SEnji Cooper fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n", 222*57718be8SEnji Cooper erbuf, (long)REG_BADPAT); 223*57718be8SEnji Cooper status = 1; 224*57718be8SEnji Cooper } 225*57718be8SEnji Cooper } 226*57718be8SEnji Cooper 227*57718be8SEnji Cooper /* 228*57718be8SEnji Cooper - try - try it, and report on problems 229*57718be8SEnji Cooper == void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts); 230*57718be8SEnji Cooper */ 231*57718be8SEnji Cooper void 232*57718be8SEnji Cooper try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts) 233*57718be8SEnji Cooper { 234*57718be8SEnji Cooper regex_t re; 235*57718be8SEnji Cooper # define NSUBS 10 236*57718be8SEnji Cooper regmatch_t subs[NSUBS]; 237*57718be8SEnji Cooper # define NSHOULD 15 238*57718be8SEnji Cooper char *should[NSHOULD]; 239*57718be8SEnji Cooper int nshould; 240*57718be8SEnji Cooper char erbuf[100]; 241*57718be8SEnji Cooper int err; 242*57718be8SEnji Cooper int len; 243*57718be8SEnji Cooper const char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE"; 244*57718be8SEnji Cooper int i; 245*57718be8SEnji Cooper char *grump; 246*57718be8SEnji Cooper char f0copy[1000]; 247*57718be8SEnji Cooper char f2copy[1000]; 248*57718be8SEnji Cooper 249*57718be8SEnji Cooper strcpy(f0copy, f0); 250*57718be8SEnji Cooper re.re_endp = (opts®_PEND) ? f0copy + strlen(f0copy) : NULL; 251*57718be8SEnji Cooper fixstr(f0copy); 252*57718be8SEnji Cooper err = regcomp(&re, f0copy, opts); 253*57718be8SEnji Cooper if (err != 0 && (!opt('C', f1) || err != efind(f2))) { 254*57718be8SEnji Cooper /* unexpected error or wrong error */ 255*57718be8SEnji Cooper len = regerror(err, &re, erbuf, sizeof(erbuf)); 256*57718be8SEnji Cooper fprintf(stderr, "%d: %s error %s, %d/%d `%s'\n", 257*57718be8SEnji Cooper line, type, eprint(err), len, 258*57718be8SEnji Cooper (int)sizeof(erbuf), erbuf); 259*57718be8SEnji Cooper status = 1; 260*57718be8SEnji Cooper } else if (err == 0 && opt('C', f1)) { 261*57718be8SEnji Cooper /* unexpected success */ 262*57718be8SEnji Cooper fprintf(stderr, "%d: %s should have given REG_%s\n", 263*57718be8SEnji Cooper line, type, f2); 264*57718be8SEnji Cooper status = 1; 265*57718be8SEnji Cooper err = 1; /* so we won't try regexec */ 266*57718be8SEnji Cooper } 267*57718be8SEnji Cooper 268*57718be8SEnji Cooper if (err != 0) { 269*57718be8SEnji Cooper regfree(&re); 270*57718be8SEnji Cooper return; 271*57718be8SEnji Cooper } 272*57718be8SEnji Cooper 273*57718be8SEnji Cooper strcpy(f2copy, f2); 274*57718be8SEnji Cooper fixstr(f2copy); 275*57718be8SEnji Cooper 276*57718be8SEnji Cooper if (options('e', f1)®_STARTEND) { 277*57718be8SEnji Cooper if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL) 278*57718be8SEnji Cooper fprintf(stderr, "%d: bad STARTEND syntax\n", line); 279*57718be8SEnji Cooper subs[0].rm_so = strchr(f2, '(') - f2 + 1; 280*57718be8SEnji Cooper subs[0].rm_eo = strchr(f2, ')') - f2; 281*57718be8SEnji Cooper } 282*57718be8SEnji Cooper err = regexec(&re, f2copy, NSUBS, subs, options('e', f1)); 283*57718be8SEnji Cooper 284*57718be8SEnji Cooper if (err != 0 && (f3 != NULL || err != REG_NOMATCH)) { 285*57718be8SEnji Cooper /* unexpected error or wrong error */ 286*57718be8SEnji Cooper len = regerror(err, &re, erbuf, sizeof(erbuf)); 287*57718be8SEnji Cooper fprintf(stderr, "%d: %s exec error %s, %d/%d `%s'\n", 288*57718be8SEnji Cooper line, type, eprint(err), len, 289*57718be8SEnji Cooper (int)sizeof(erbuf), erbuf); 290*57718be8SEnji Cooper status = 1; 291*57718be8SEnji Cooper } else if (err != 0) { 292*57718be8SEnji Cooper /* nothing more to check */ 293*57718be8SEnji Cooper } else if (f3 == NULL) { 294*57718be8SEnji Cooper /* unexpected success */ 295*57718be8SEnji Cooper fprintf(stderr, "%d: %s exec should have failed\n", 296*57718be8SEnji Cooper line, type); 297*57718be8SEnji Cooper status = 1; 298*57718be8SEnji Cooper err = 1; /* just on principle */ 299*57718be8SEnji Cooper } else if (opts®_NOSUB) { 300*57718be8SEnji Cooper /* nothing more to check */ 301*57718be8SEnji Cooper } else if ((grump = check(f2, subs[0], f3)) != NULL) { 302*57718be8SEnji Cooper fprintf(stderr, "%d: %s %s\n", line, type, grump); 303*57718be8SEnji Cooper status = 1; 304*57718be8SEnji Cooper err = 1; 305*57718be8SEnji Cooper } 306*57718be8SEnji Cooper 307*57718be8SEnji Cooper if (err != 0 || f4 == NULL) { 308*57718be8SEnji Cooper regfree(&re); 309*57718be8SEnji Cooper return; 310*57718be8SEnji Cooper } 311*57718be8SEnji Cooper 312*57718be8SEnji Cooper for (i = 1; i < NSHOULD; i++) 313*57718be8SEnji Cooper should[i] = NULL; 314*57718be8SEnji Cooper nshould = split(f4, &should[1], NSHOULD-1, ","); 315*57718be8SEnji Cooper if (nshould == 0) { 316*57718be8SEnji Cooper nshould = 1; 317*57718be8SEnji Cooper should[1] = ∅ 318*57718be8SEnji Cooper } 319*57718be8SEnji Cooper for (i = 1; i < NSUBS; i++) { 320*57718be8SEnji Cooper grump = check(f2, subs[i], should[i]); 321*57718be8SEnji Cooper if (grump != NULL) { 322*57718be8SEnji Cooper fprintf(stderr, "%d: %s $%d %s\n", line, 323*57718be8SEnji Cooper type, i, grump); 324*57718be8SEnji Cooper status = 1; 325*57718be8SEnji Cooper err = 1; 326*57718be8SEnji Cooper } 327*57718be8SEnji Cooper } 328*57718be8SEnji Cooper 329*57718be8SEnji Cooper regfree(&re); 330*57718be8SEnji Cooper } 331*57718be8SEnji Cooper 332*57718be8SEnji Cooper /* 333*57718be8SEnji Cooper - options - pick options out of a regression-test string 334*57718be8SEnji Cooper == int options(int type, char *s); 335*57718be8SEnji Cooper */ 336*57718be8SEnji Cooper int 337*57718be8SEnji Cooper options(int type, char *s) 338*57718be8SEnji Cooper { 339*57718be8SEnji Cooper char *p; 340*57718be8SEnji Cooper int o = (type == 'c') ? copts : eopts; 341*57718be8SEnji Cooper const char *legal = (type == 'c') ? "bisnmp" : "^$#tl"; 342*57718be8SEnji Cooper 343*57718be8SEnji Cooper for (p = s; *p != '\0'; p++) 344*57718be8SEnji Cooper if (strchr(legal, *p) != NULL) 345*57718be8SEnji Cooper switch (*p) { 346*57718be8SEnji Cooper case 'b': 347*57718be8SEnji Cooper o &= ~REG_EXTENDED; 348*57718be8SEnji Cooper break; 349*57718be8SEnji Cooper case 'i': 350*57718be8SEnji Cooper o |= REG_ICASE; 351*57718be8SEnji Cooper break; 352*57718be8SEnji Cooper case 's': 353*57718be8SEnji Cooper o |= REG_NOSUB; 354*57718be8SEnji Cooper break; 355*57718be8SEnji Cooper case 'n': 356*57718be8SEnji Cooper o |= REG_NEWLINE; 357*57718be8SEnji Cooper break; 358*57718be8SEnji Cooper case 'm': 359*57718be8SEnji Cooper o &= ~REG_EXTENDED; 360*57718be8SEnji Cooper o |= REG_NOSPEC; 361*57718be8SEnji Cooper break; 362*57718be8SEnji Cooper case 'p': 363*57718be8SEnji Cooper o |= REG_PEND; 364*57718be8SEnji Cooper break; 365*57718be8SEnji Cooper case '^': 366*57718be8SEnji Cooper o |= REG_NOTBOL; 367*57718be8SEnji Cooper break; 368*57718be8SEnji Cooper case '$': 369*57718be8SEnji Cooper o |= REG_NOTEOL; 370*57718be8SEnji Cooper break; 371*57718be8SEnji Cooper case '#': 372*57718be8SEnji Cooper o |= REG_STARTEND; 373*57718be8SEnji Cooper break; 374*57718be8SEnji Cooper case 't': /* trace */ 375*57718be8SEnji Cooper o |= REG_TRACE; 376*57718be8SEnji Cooper break; 377*57718be8SEnji Cooper case 'l': /* force long representation */ 378*57718be8SEnji Cooper o |= REG_LARGE; 379*57718be8SEnji Cooper break; 380*57718be8SEnji Cooper case 'r': /* force backref use */ 381*57718be8SEnji Cooper o |= REG_BACKR; 382*57718be8SEnji Cooper break; 383*57718be8SEnji Cooper } 384*57718be8SEnji Cooper return(o); 385*57718be8SEnji Cooper } 386*57718be8SEnji Cooper 387*57718be8SEnji Cooper /* 388*57718be8SEnji Cooper - opt - is a particular option in a regression string? 389*57718be8SEnji Cooper == int opt(int c, char *s); 390*57718be8SEnji Cooper */ 391*57718be8SEnji Cooper int /* predicate */ 392*57718be8SEnji Cooper opt(int c, char *s) 393*57718be8SEnji Cooper { 394*57718be8SEnji Cooper return(strchr(s, c) != NULL); 395*57718be8SEnji Cooper } 396*57718be8SEnji Cooper 397*57718be8SEnji Cooper /* 398*57718be8SEnji Cooper - fixstr - transform magic characters in strings 399*57718be8SEnji Cooper == void fixstr(char *p); 400*57718be8SEnji Cooper */ 401*57718be8SEnji Cooper void 402*57718be8SEnji Cooper fixstr(char *p) 403*57718be8SEnji Cooper { 404*57718be8SEnji Cooper if (p == NULL) 405*57718be8SEnji Cooper return; 406*57718be8SEnji Cooper 407*57718be8SEnji Cooper for (; *p != '\0'; p++) 408*57718be8SEnji Cooper if (*p == 'N') 409*57718be8SEnji Cooper *p = '\n'; 410*57718be8SEnji Cooper else if (*p == 'T') 411*57718be8SEnji Cooper *p = '\t'; 412*57718be8SEnji Cooper else if (*p == 'S') 413*57718be8SEnji Cooper *p = ' '; 414*57718be8SEnji Cooper else if (*p == 'Z') 415*57718be8SEnji Cooper *p = '\0'; 416*57718be8SEnji Cooper } 417*57718be8SEnji Cooper 418*57718be8SEnji Cooper /* 419*57718be8SEnji Cooper * check - check a substring match 420*57718be8SEnji Cooper */ 421*57718be8SEnji Cooper char * /* NULL or complaint */ 422*57718be8SEnji Cooper check(char *str, regmatch_t sub, char *should) 423*57718be8SEnji Cooper { 424*57718be8SEnji Cooper int len; 425*57718be8SEnji Cooper int shlen; 426*57718be8SEnji Cooper char *p; 427*57718be8SEnji Cooper static char grump[500]; 428*57718be8SEnji Cooper char *at = NULL; 429*57718be8SEnji Cooper 430*57718be8SEnji Cooper if (should != NULL && strcmp(should, "-") == 0) 431*57718be8SEnji Cooper should = NULL; 432*57718be8SEnji Cooper if (should != NULL && should[0] == '@') { 433*57718be8SEnji Cooper at = should + 1; 434*57718be8SEnji Cooper should = ∅ 435*57718be8SEnji Cooper } 436*57718be8SEnji Cooper 437*57718be8SEnji Cooper /* check rm_so and rm_eo for consistency */ 438*57718be8SEnji Cooper if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) || 439*57718be8SEnji Cooper (sub.rm_so != -1 && sub.rm_eo == -1) || 440*57718be8SEnji Cooper (sub.rm_so != -1 && sub.rm_so < 0) || 441*57718be8SEnji Cooper (sub.rm_eo != -1 && sub.rm_eo < 0) ) { 442*57718be8SEnji Cooper sprintf(grump, "start %ld end %ld", (long)sub.rm_so, 443*57718be8SEnji Cooper (long)sub.rm_eo); 444*57718be8SEnji Cooper return(grump); 445*57718be8SEnji Cooper } 446*57718be8SEnji Cooper 447*57718be8SEnji Cooper /* check for no match */ 448*57718be8SEnji Cooper if (sub.rm_so == -1) { 449*57718be8SEnji Cooper if (should == NULL) 450*57718be8SEnji Cooper return(NULL); 451*57718be8SEnji Cooper else { 452*57718be8SEnji Cooper sprintf(grump, "did not match"); 453*57718be8SEnji Cooper return(grump); 454*57718be8SEnji Cooper } 455*57718be8SEnji Cooper } 456*57718be8SEnji Cooper 457*57718be8SEnji Cooper /* check for in range */ 458*57718be8SEnji Cooper if (sub.rm_eo > (ssize_t)strlen(str)) { 459*57718be8SEnji Cooper sprintf(grump, "start %ld end %ld, past end of string", 460*57718be8SEnji Cooper (long)sub.rm_so, (long)sub.rm_eo); 461*57718be8SEnji Cooper return(grump); 462*57718be8SEnji Cooper } 463*57718be8SEnji Cooper 464*57718be8SEnji Cooper len = (int)(sub.rm_eo - sub.rm_so); 465*57718be8SEnji Cooper p = str + sub.rm_so; 466*57718be8SEnji Cooper 467*57718be8SEnji Cooper /* check for not supposed to match */ 468*57718be8SEnji Cooper if (should == NULL) { 469*57718be8SEnji Cooper sprintf(grump, "matched `%.*s'", len, p); 470*57718be8SEnji Cooper return(grump); 471*57718be8SEnji Cooper } 472*57718be8SEnji Cooper 473*57718be8SEnji Cooper /* check for wrong match */ 474*57718be8SEnji Cooper shlen = (int)strlen(should); 475*57718be8SEnji Cooper if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) { 476*57718be8SEnji Cooper sprintf(grump, "matched `%.*s' instead", len, p); 477*57718be8SEnji Cooper return(grump); 478*57718be8SEnji Cooper } 479*57718be8SEnji Cooper if (shlen > 0) 480*57718be8SEnji Cooper return(NULL); 481*57718be8SEnji Cooper 482*57718be8SEnji Cooper /* check null match in right place */ 483*57718be8SEnji Cooper if (at == NULL) 484*57718be8SEnji Cooper return(NULL); 485*57718be8SEnji Cooper shlen = strlen(at); 486*57718be8SEnji Cooper if (shlen == 0) 487*57718be8SEnji Cooper shlen = 1; /* force check for end-of-string */ 488*57718be8SEnji Cooper if (strncmp(p, at, shlen) != 0) { 489*57718be8SEnji Cooper sprintf(grump, "matched null at `%.20s'", p); 490*57718be8SEnji Cooper return(grump); 491*57718be8SEnji Cooper } 492*57718be8SEnji Cooper return(NULL); 493*57718be8SEnji Cooper } 494*57718be8SEnji Cooper 495*57718be8SEnji Cooper /* 496*57718be8SEnji Cooper * eprint - convert error number to name 497*57718be8SEnji Cooper */ 498*57718be8SEnji Cooper static char * 499*57718be8SEnji Cooper eprint(int err) 500*57718be8SEnji Cooper { 501*57718be8SEnji Cooper static char epbuf[100]; 502*57718be8SEnji Cooper size_t len; 503*57718be8SEnji Cooper 504*57718be8SEnji Cooper len = regerror(REG_ITOA|err, NULL, epbuf, sizeof(epbuf)); 505*57718be8SEnji Cooper assert(len <= sizeof(epbuf)); 506*57718be8SEnji Cooper return(epbuf); 507*57718be8SEnji Cooper } 508*57718be8SEnji Cooper 509*57718be8SEnji Cooper /* 510*57718be8SEnji Cooper * efind - convert error name to number 511*57718be8SEnji Cooper */ 512*57718be8SEnji Cooper static int 513*57718be8SEnji Cooper efind(char *name) 514*57718be8SEnji Cooper { 515*57718be8SEnji Cooper static char efbuf[100]; 516*57718be8SEnji Cooper regex_t re; 517*57718be8SEnji Cooper 518*57718be8SEnji Cooper sprintf(efbuf, "REG_%s", name); 519*57718be8SEnji Cooper assert(strlen(efbuf) < sizeof(efbuf)); 520*57718be8SEnji Cooper re.re_endp = efbuf; 521*57718be8SEnji Cooper (void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf)); 522*57718be8SEnji Cooper return(atoi(efbuf)); 523*57718be8SEnji Cooper } 524