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

Contents of /code/trunk/pcretest.c

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12