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