~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to regex/main.c

Replaced regex lib with pcre. Reworked mysqltest to use it. 

Show diffs side-by-side

added added

removed removed

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