/[pcre]/code/trunk/pcretest.c
ViewVC logotype

Contents of /code/trunk/pcretest.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations) (download)
Sat Feb 24 21:38:41 2007 UTC (7 years, 6 months ago) by nigel
File MIME type: text/plain
File size: 20300 byte(s)
Load pcre-2.00 into code/trunk.

1 /*************************************************
2 * PCRE testing program *
3 *************************************************/
4
5 #include <ctype.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <time.h>
10
11 /* Use the internal info for displaying the results of pcre_study(). */
12
13 #include "internal.h"
14 #include "pcreposix.h"
15
16 #ifndef CLOCKS_PER_SEC
17 #ifdef CLK_TCK
18 #define CLOCKS_PER_SEC CLK_TCK
19 #else
20 #define CLOCKS_PER_SEC 100
21 #endif
22 #endif
23
24 #define LOOPREPEAT 10000
25
26
27 static FILE *outfile;
28 static int log_store = 0;
29
30
31
32 /* Debugging function to print the internal form of the regex. This is the same
33 code as contained in pcre.c under the DEBUG macro. */
34
35 static const char *OP_names[] = {
36 "End", "\\A", "\\B", "\\b", "\\D", "\\d",
37 "\\S", "\\s", "\\W", "\\w", "\\Z", "\\z",
38 "Opt", "^", "$", "Any", "chars", "not",
39 "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
40 "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
41 "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
42 "*", "*?", "+", "+?", "?", "??", "{", "{",
43 "class", "Ref",
44 "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not",
45 "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cref",
46 "Brazero", "Braminzero", "Bra"
47 };
48
49
50 static void print_internals(pcre *re, FILE *outfile)
51 {
52 unsigned char *code = ((real_pcre *)re)->code;
53
54 fprintf(outfile, "------------------------------------------------------------------\n");
55
56 for(;;)
57 {
58 int c;
59 int charlength;
60
61 fprintf(outfile, "%3d ", (int)(code - ((real_pcre *)re)->code));
62
63 if (*code >= OP_BRA)
64 {
65 fprintf(outfile, "%3d Bra %d", (code[1] << 8) + code[2], *code - OP_BRA);
66 code += 2;
67 }
68
69 else switch(*code)
70 {
71 case OP_END:
72 fprintf(outfile, " %s\n", OP_names[*code]);
73 fprintf(outfile, "------------------------------------------------------------------\n");
74 return;
75
76 case OP_OPT:
77 fprintf(outfile, " %.2x %s", code[1], OP_names[*code]);
78 code++;
79 break;
80
81 case OP_COND:
82 fprintf(outfile, "%3d Cond", (code[1] << 8) + code[2]);
83 code += 2;
84 break;
85
86 case OP_CREF:
87 fprintf(outfile, " %.2d %s", code[1], OP_names[*code]);
88 code++;
89 break;
90
91 case OP_CHARS:
92 charlength = *(++code);
93 fprintf(outfile, "%3d ", charlength);
94 while (charlength-- > 0)
95 if (isprint(c = *(++code))) fprintf(outfile, "%c", c);
96 else fprintf(outfile, "\\x%02x", c);
97 break;
98
99 case OP_KETRMAX:
100 case OP_KETRMIN:
101 case OP_ALT:
102 case OP_KET:
103 case OP_ASSERT:
104 case OP_ASSERT_NOT:
105 case OP_ASSERTBACK:
106 case OP_ASSERTBACK_NOT:
107 case OP_ONCE:
108 fprintf(outfile, "%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
109 code += 2;
110 break;
111
112 case OP_REVERSE:
113 fprintf(outfile, "%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
114 code += 2;
115 break;
116
117 case OP_STAR:
118 case OP_MINSTAR:
119 case OP_PLUS:
120 case OP_MINPLUS:
121 case OP_QUERY:
122 case OP_MINQUERY:
123 case OP_TYPESTAR:
124 case OP_TYPEMINSTAR:
125 case OP_TYPEPLUS:
126 case OP_TYPEMINPLUS:
127 case OP_TYPEQUERY:
128 case OP_TYPEMINQUERY:
129 if (*code >= OP_TYPESTAR)
130 fprintf(outfile, " %s", OP_names[code[1]]);
131 else if (isprint(c = code[1])) fprintf(outfile, " %c", c);
132 else fprintf(outfile, " \\x%02x", c);
133 fprintf(outfile, "%s", OP_names[*code++]);
134 break;
135
136 case OP_EXACT:
137 case OP_UPTO:
138 case OP_MINUPTO:
139 if (isprint(c = code[3])) fprintf(outfile, " %c{", c);
140 else fprintf(outfile, " \\x%02x{", c);
141 if (*code != OP_EXACT) fprintf(outfile, ",");
142 fprintf(outfile, "%d}", (code[1] << 8) + code[2]);
143 if (*code == OP_MINUPTO) fprintf(outfile, "?");
144 code += 3;
145 break;
146
147 case OP_TYPEEXACT:
148 case OP_TYPEUPTO:
149 case OP_TYPEMINUPTO:
150 fprintf(outfile, " %s{", OP_names[code[3]]);
151 if (*code != OP_TYPEEXACT) fprintf(outfile, "0,");
152 fprintf(outfile, "%d}", (code[1] << 8) + code[2]);
153 if (*code == OP_TYPEMINUPTO) fprintf(outfile, "?");
154 code += 3;
155 break;
156
157 case OP_NOT:
158 if (isprint(c = *(++code))) fprintf(outfile, " [^%c]", c);
159 else fprintf(outfile, " [^\\x%02x]", c);
160 break;
161
162 case OP_NOTSTAR:
163 case OP_NOTMINSTAR:
164 case OP_NOTPLUS:
165 case OP_NOTMINPLUS:
166 case OP_NOTQUERY:
167 case OP_NOTMINQUERY:
168 if (isprint(c = code[1])) fprintf(outfile, " [^%c]", c);
169 else fprintf(outfile, " [^\\x%02x]", c);
170 fprintf(outfile, "%s", OP_names[*code++]);
171 break;
172
173 case OP_NOTEXACT:
174 case OP_NOTUPTO:
175 case OP_NOTMINUPTO:
176 if (isprint(c = code[3])) fprintf(outfile, " [^%c]{", c);
177 else fprintf(outfile, " [^\\x%02x]{", c);
178 if (*code != OP_NOTEXACT) fprintf(outfile, ",");
179 fprintf(outfile, "%d}", (code[1] << 8) + code[2]);
180 if (*code == OP_NOTMINUPTO) fprintf(outfile, "?");
181 code += 3;
182 break;
183
184 case OP_REF:
185 fprintf(outfile, " \\%d", *(++code));
186 code++;
187 goto CLASS_REF_REPEAT;
188
189 case OP_CLASS:
190 {
191 int i, min, max;
192 code++;
193 fprintf(outfile, " [");
194
195 for (i = 0; i < 256; i++)
196 {
197 if ((code[i/8] & (1 << (i&7))) != 0)
198 {
199 int j;
200 for (j = i+1; j < 256; j++)
201 if ((code[j/8] & (1 << (j&7))) == 0) break;
202 if (i == '-' || i == ']') fprintf(outfile, "\\");
203 if (isprint(i)) fprintf(outfile, "%c", i); else fprintf(outfile, "\\x%02x", i);
204 if (--j > i)
205 {
206 fprintf(outfile, "-");
207 if (j == '-' || j == ']') fprintf(outfile, "\\");
208 if (isprint(j)) fprintf(outfile, "%c", j); else fprintf(outfile, "\\x%02x", j);
209 }
210 i = j;
211 }
212 }
213 fprintf(outfile, "]");
214 code += 32;
215
216 CLASS_REF_REPEAT:
217
218 switch(*code)
219 {
220 case OP_CRSTAR:
221 case OP_CRMINSTAR:
222 case OP_CRPLUS:
223 case OP_CRMINPLUS:
224 case OP_CRQUERY:
225 case OP_CRMINQUERY:
226 fprintf(outfile, "%s", OP_names[*code]);
227 break;
228
229 case OP_CRRANGE:
230 case OP_CRMINRANGE:
231 min = (code[1] << 8) + code[2];
232 max = (code[3] << 8) + code[4];
233 if (max == 0) fprintf(outfile, "{%d,}", min);
234 else fprintf(outfile, "{%d,%d}", min, max);
235 if (*code == OP_CRMINRANGE) fprintf(outfile, "?");
236 code += 4;
237 break;
238
239 default:
240 code--;
241 }
242 }
243 break;
244
245 /* Anything else is just a one-node item */
246
247 default:
248 fprintf(outfile, " %s", OP_names[*code]);
249 break;
250 }
251
252 code++;
253 fprintf(outfile, "\n");
254 }
255 }
256
257
258
259 /* Character string printing function. */
260
261 static void pchars(unsigned char *p, int length)
262 {
263 int c;
264 while (length-- > 0)
265 if (isprint(c = *(p++))) fprintf(outfile, "%c", c);
266 else fprintf(outfile, "\\x%02x", c);
267 }
268
269
270
271 /* Alternative malloc function, to test functionality and show the size of the
272 compiled re. */
273
274 static void *new_malloc(size_t size)
275 {
276 if (log_store) fprintf(outfile, "Store size request: %d\n", (int)size);
277 return malloc(size);
278 }
279
280
281
282 /* Read lines from named file or stdin and write to named file or stdout; lines
283 consist of a regular expression, in delimiters and optionally followed by
284 options, followed by a set of test data, terminated by an empty line. */
285
286 int main(int argc, char **argv)
287 {
288 FILE *infile = stdin;
289 int options = 0;
290 int study_options = 0;
291 int op = 1;
292 int timeit = 0;
293 int showinfo = 0;
294 int posix = 0;
295 int debug = 0;
296 int done = 0;
297 unsigned char buffer[30000];
298 unsigned char dbuffer[1024];
299
300 /* Static so that new_malloc can use it. */
301
302 outfile = stdout;
303
304 /* Scan options */
305
306 while (argc > 1 && argv[op][0] == '-')
307 {
308 if (strcmp(argv[op], "-s") == 0) log_store = 1;
309 else if (strcmp(argv[op], "-t") == 0) timeit = 1;
310 else if (strcmp(argv[op], "-i") == 0) showinfo = 1;
311 else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1;
312 else if (strcmp(argv[op], "-p") == 0) posix = 1;
313 else
314 {
315 printf("*** Unknown option %s\n", argv[op]);
316 return 1;
317 }
318 op++;
319 argc--;
320 }
321
322 /* Sort out the input and output files */
323
324 if (argc > 1)
325 {
326 infile = fopen(argv[op], "r");
327 if (infile == NULL)
328 {
329 printf("** Failed to open %s\n", argv[op]);
330 return 1;
331 }
332 }
333
334 if (argc > 2)
335 {
336 outfile = fopen(argv[op+1], "w");
337 if (outfile == NULL)
338 {
339 printf("** Failed to open %s\n", argv[op+1]);
340 return 1;
341 }
342 }
343
344 /* Set alternative malloc function */
345
346 pcre_malloc = new_malloc;
347
348 /* Heading line, then prompt for first regex if stdin */
349
350 fprintf(outfile, "PCRE version %s\n\n", pcre_version());
351
352 /* Main loop */
353
354 while (!done)
355 {
356 pcre *re = NULL;
357 pcre_extra *extra = NULL;
358 regex_t preg;
359 const char *error;
360 unsigned char *p, *pp;
361 int do_study = 0;
362 int do_debug = 0;
363 int do_posix = 0;
364 int erroroffset, len, delimiter;
365
366 if (infile == stdin) printf(" re> ");
367 if (fgets((char *)buffer, sizeof(buffer), infile) == NULL) break;
368 if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
369
370 p = buffer;
371 while (isspace(*p)) p++;
372 if (*p == 0) continue;
373
374 /* Get the delimiter and seek the end of the pattern; if is isn't
375 complete, read more. */
376
377 delimiter = *p++;
378
379 if (isalnum(delimiter))
380 {
381 fprintf(outfile, "** Delimiter must not be alphameric\n");
382 goto SKIP_DATA;
383 }
384
385 pp = p;
386
387 for(;;)
388 {
389 while (*pp != 0 && *pp != delimiter) pp++;
390 if (*pp != 0) break;
391
392 len = sizeof(buffer) - (pp - buffer);
393 if (len < 256)
394 {
395 fprintf(outfile, "** Expression too long - missing delimiter?\n");
396 goto SKIP_DATA;
397 }
398
399 if (infile == stdin) printf(" > ");
400 if (fgets((char *)pp, len, infile) == NULL)
401 {
402 fprintf(outfile, "** Unexpected EOF\n");
403 done = 1;
404 goto CONTINUE;
405 }
406 if (infile != stdin) fprintf(outfile, "%s", (char *)pp);
407 }
408
409 /* Terminate the pattern at the delimiter */
410
411 *pp++ = 0;
412
413 /* Look for options after final delimiter */
414
415 options = 0;
416 study_options = 0;
417 while (*pp != 0)
418 {
419 switch (*pp++)
420 {
421 case 'i': options |= PCRE_CASELESS; break;
422 case 'm': options |= PCRE_MULTILINE; break;
423 case 's': options |= PCRE_DOTALL; break;
424 case 'x': options |= PCRE_EXTENDED; break;
425 case 'A': options |= PCRE_ANCHORED; break;
426 case 'D': do_debug = 1; break;
427 case 'E': options |= PCRE_DOLLAR_ENDONLY; break;
428 case 'P': do_posix = 1; break;
429 case 'S': do_study = 1; break;
430 case 'U': options |= PCRE_UNGREEDY; break;
431 case 'X': options |= PCRE_EXTRA; break;
432 case '\n': case ' ': break;
433 default:
434 fprintf(outfile, "** Unknown option '%c'\n", pp[-1]);
435 goto SKIP_DATA;
436 }
437 }
438
439 /* Handle compiling via the POSIX interface, which doesn't support the
440 timing, showing, or debugging options. */
441
442 if (posix || do_posix)
443 {
444 int rc;
445 int cflags = 0;
446 if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE;
447 if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE;
448 rc = regcomp(&preg, (char *)p, cflags);
449
450 /* Compilation failed; go back for another re, skipping to blank line
451 if non-interactive. */
452
453 if (rc != 0)
454 {
455 (void)regerror(rc, &preg, (char *)buffer, sizeof(buffer));
456 fprintf(outfile, "Failed: POSIX code %d: %s\n", rc, buffer);
457 goto SKIP_DATA;
458 }
459 }
460
461 /* Handle compiling via the native interface */
462
463 else
464 {
465 if (timeit)
466 {
467 register int i;
468 clock_t time_taken;
469 clock_t start_time = clock();
470 for (i = 0; i < LOOPREPEAT; i++)
471 {
472 re = pcre_compile((char *)p, options, &error, &erroroffset);
473 if (re != NULL) free(re);
474 }
475 time_taken = clock() - start_time;
476 fprintf(outfile, "Compile time %.2f milliseconds\n",
477 ((double)time_taken)/(4 * CLOCKS_PER_SEC));
478 }
479
480 re = pcre_compile((char *)p, options, &error, &erroroffset);
481
482 /* Compilation failed; go back for another re, skipping to blank line
483 if non-interactive. */
484
485 if (re == NULL)
486 {
487 fprintf(outfile, "Failed: %s at offset %d\n", error, erroroffset);
488 SKIP_DATA:
489 if (infile != stdin)
490 {
491 for (;;)
492 {
493 if (fgets((char *)buffer, sizeof(buffer), infile) == NULL)
494 {
495 done = 1;
496 goto CONTINUE;
497 }
498 len = (int)strlen((char *)buffer);
499 while (len > 0 && isspace(buffer[len-1])) len--;
500 if (len == 0) break;
501 }
502 fprintf(outfile, "\n");
503 }
504 continue;
505 }
506
507 /* Compilation succeeded; print data if required */
508
509 if (showinfo || do_debug)
510 {
511 int first_char, count;
512
513 if (debug || do_debug) print_internals(re, outfile);
514
515 count = pcre_info(re, &options, &first_char);
516 if (count < 0) fprintf(outfile,
517 "Error %d while reading info\n", count);
518 else
519 {
520 fprintf(outfile, "Identifying subpattern count = %d\n", count);
521 if (options == 0) fprintf(outfile, "No options\n");
522 else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s\n",
523 ((options & PCRE_ANCHORED) != 0)? " anchored" : "",
524 ((options & PCRE_CASELESS) != 0)? " caseless" : "",
525 ((options & PCRE_EXTENDED) != 0)? " extended" : "",
526 ((options & PCRE_MULTILINE) != 0)? " multiline" : "",
527 ((options & PCRE_DOTALL) != 0)? " dotall" : "",
528 ((options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",
529 ((options & PCRE_EXTRA) != 0)? " extra" : "",
530 ((options & PCRE_UNGREEDY) != 0)? " ungreedy" : "");
531 if (first_char == -1)
532 {
533 fprintf(outfile, "First char at start or follows \\n\n");
534 }
535 else if (first_char < 0)
536 {
537 fprintf(outfile, "No first char\n");
538 }
539 else
540 {
541 if (isprint(first_char))
542 fprintf(outfile, "First char = \'%c\'\n", first_char);
543 else
544 fprintf(outfile, "First char = %d\n", first_char);
545 }
546 }
547 }
548
549 /* If /S was present, study the regexp to generate additional info to
550 help with the matching. */
551
552 if (do_study)
553 {
554 if (timeit)
555 {
556 register int i;
557 clock_t time_taken;
558 clock_t start_time = clock();
559 for (i = 0; i < LOOPREPEAT; i++)
560 extra = pcre_study(re, study_options, &error);
561 time_taken = clock() - start_time;
562 if (extra != NULL) free(extra);
563 fprintf(outfile, " Study time %.2f milliseconds\n",
564 ((double)time_taken)/(4 * CLOCKS_PER_SEC));
565 }
566
567 extra = pcre_study(re, study_options, &error);
568 if (error != NULL)
569 fprintf(outfile, "Failed to study: %s\n", error);
570 else if (extra == NULL)
571 fprintf(outfile, "Study returned NULL\n");
572
573 /* This looks at internal information. A bit kludgy to do it this
574 way, but it is useful for testing. */
575
576 else if (showinfo || do_debug)
577 {
578 real_pcre_extra *xx = (real_pcre_extra *)extra;
579 if ((xx->options & PCRE_STUDY_MAPPED) == 0)
580 fprintf(outfile, "No starting character set\n");
581 else
582 {
583 int i;
584 int c = 24;
585 fprintf(outfile, "Starting character set: ");
586 for (i = 0; i < 256; i++)
587 {
588 if ((xx->start_bits[i/8] & (1<<(i%8))) != 0)
589 {
590 if (c > 75)
591 {
592 fprintf(outfile, "\n ");
593 c = 2;
594 }
595 if (isprint(i) && i != ' ')
596 {
597 fprintf(outfile, "%c ", i);
598 c += 2;
599 }
600 else
601 {
602 fprintf(outfile, "\\x%02x ", i);
603 c += 5;
604 }
605 }
606 }
607 fprintf(outfile, "\n");
608 }
609 }
610 }
611 }
612
613 /* Read data lines and test them */
614
615 for (;;)
616 {
617 unsigned char *q;
618 int count, c;
619 int offsets[45];
620 int size_offsets = sizeof(offsets)/sizeof(int);
621
622 options = 0;
623
624 if (infile == stdin) printf(" data> ");
625 if (fgets((char *)buffer, sizeof(buffer), infile) == NULL)
626 {
627 done = 1;
628 goto CONTINUE;
629 }
630 if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
631
632 len = (int)strlen((char *)buffer);
633 while (len > 0 && isspace(buffer[len-1])) len--;
634 buffer[len] = 0;
635 if (len == 0) break;
636
637 p = buffer;
638 while (isspace(*p)) p++;
639
640 q = dbuffer;
641 while ((c = *p++) != 0)
642 {
643 int i = 0;
644 int n = 0;
645 if (c == '\\') switch ((c = *p++))
646 {
647 case 'a': c = 7; break;
648 case 'b': c = '\b'; break;
649 case 'e': c = 27; break;
650 case 'f': c = '\f'; break;
651 case 'n': c = '\n'; break;
652 case 'r': c = '\r'; break;
653 case 't': c = '\t'; break;
654 case 'v': c = '\v'; break;
655
656 case '0': case '1': case '2': case '3':
657 case '4': case '5': case '6': case '7':
658 c -= '0';
659 while (i++ < 2 && isdigit(*p) && *p != '8' && *p != '9')
660 c = c * 8 + *p++ - '0';
661 break;
662
663 case 'x':
664 c = 0;
665 while (i++ < 2 && isxdigit(*p))
666 {
667 c = c * 16 + tolower(*p) - ((isdigit(*p))? '0' : 'W');
668 p++;
669 }
670 break;
671
672 case 0: /* Allows for an empty line */
673 p--;
674 continue;
675
676 case 'A': /* Option setting */
677 options |= PCRE_ANCHORED;
678 continue;
679
680 case 'B':
681 options |= PCRE_NOTBOL;
682 continue;
683
684 case 'O':
685 while(isdigit(*p)) n = n * 10 + *p++ - '0';
686 if (n <= (int)(sizeof(offsets)/sizeof(int))) size_offsets = n;
687 continue;
688
689 case 'Z':
690 options |= PCRE_NOTEOL;
691 continue;
692 }
693 *q++ = c;
694 }
695 *q = 0;
696 len = q - dbuffer;
697
698 /* Handle matching via the POSIX interface, which does not
699 support timing. */
700
701 if (posix || do_posix)
702 {
703 int rc;
704 int eflags = 0;
705 regmatch_t pmatch[30];
706 if ((options & PCRE_NOTBOL) != 0) eflags |= REG_NOTBOL;
707 if ((options & PCRE_NOTEOL) != 0) eflags |= REG_NOTEOL;
708
709 rc = regexec(&preg, (char *)dbuffer, sizeof(pmatch)/sizeof(regmatch_t),
710 pmatch, eflags);
711
712 if (rc != 0)
713 {
714 (void)regerror(rc, &preg, (char *)buffer, sizeof(buffer));
715 fprintf(outfile, "No match: POSIX code %d: %s\n", rc, buffer);
716 }
717 else
718 {
719 size_t i;
720 for (i = 0; i < sizeof(pmatch)/sizeof(regmatch_t); i++)
721 {
722 if (pmatch[i].rm_so >= 0)
723 {
724 fprintf(outfile, "%2d: ", (int)i);
725 pchars(dbuffer + pmatch[i].rm_so,
726 pmatch[i].rm_eo - pmatch[i].rm_so);
727 fprintf(outfile, "\n");
728 }
729 }
730 }
731 }
732
733 /* Handle matching via the native interface */
734
735 else
736 {
737 if (timeit)
738 {
739 register int i;
740 clock_t time_taken;
741 clock_t start_time = clock();
742 for (i = 0; i < 4000; i++)
743 count = pcre_exec(re, extra, (char *)dbuffer, len, options, offsets,
744 size_offsets);
745 time_taken = clock() - start_time;
746 fprintf(outfile, "Execute time %.2f milliseconds\n",
747 ((double)time_taken)/(4 * CLOCKS_PER_SEC));
748 }
749
750 count = pcre_exec(re, extra, (char *)dbuffer, len, options, offsets,
751 size_offsets);
752
753 if (count == 0)
754 {
755 fprintf(outfile, "Matched, but too many substrings\n");
756 count = size_offsets/3;
757 }
758
759 if (count >= 0)
760 {
761 int i;
762 count *= 2;
763 for (i = 0; i < count; i += 2)
764 {
765 if (offsets[i] < 0)
766 fprintf(outfile, "%2d: <unset>\n", i/2);
767 else
768 {
769 fprintf(outfile, "%2d: ", i/2);
770 pchars(dbuffer + offsets[i], offsets[i+1] - offsets[i]);
771 fprintf(outfile, "\n");
772 }
773 }
774 }
775 else
776 {
777 if (count == -1) fprintf(outfile, "No match\n");
778 else fprintf(outfile, "Error %d\n", count);
779 }
780 }
781 }
782
783 CONTINUE:
784 if (posix || do_posix) regfree(&preg);
785 if (re != NULL) free(re);
786 if (extra != NULL) free(extra);
787 }
788
789 fprintf(outfile, "\n");
790 return 0;
791 }
792
793 /* End */

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12