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

Contents of /code/trunk/pcretest.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Sat Feb 24 21:38:57 2007 UTC (7 years, 1 month ago) by nigel
File MIME type: text/plain
File size: 23879 byte(s)
Load pcre-2.04 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 20000
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)
278 fprintf(outfile, "Memory allocation request: %d (code space %d)\n",
279 (int)size, (int)size - offsetof(real_pcre, code[0]));
280 return malloc(size);
281 }
282
283
284
285 /* Read lines from named file or stdin and write to named file or stdout; lines
286 consist of a regular expression, in delimiters and optionally followed by
287 options, followed by a set of test data, terminated by an empty line. */
288
289 int main(int argc, char **argv)
290 {
291 FILE *infile = stdin;
292 int options = 0;
293 int study_options = 0;
294 int op = 1;
295 int timeit = 0;
296 int showinfo = 0;
297 int showstore = 0;
298 int posix = 0;
299 int debug = 0;
300 int done = 0;
301 unsigned char buffer[30000];
302 unsigned char dbuffer[1024];
303
304 /* Static so that new_malloc can use it. */
305
306 outfile = stdout;
307
308 /* Scan options */
309
310 while (argc > 1 && argv[op][0] == '-')
311 {
312 if (strcmp(argv[op], "-s") == 0 || strcmp(argv[op], "-m") == 0)
313 showstore = 1;
314 else if (strcmp(argv[op], "-t") == 0) timeit = 1;
315 else if (strcmp(argv[op], "-i") == 0) showinfo = 1;
316 else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1;
317 else if (strcmp(argv[op], "-p") == 0) posix = 1;
318 else
319 {
320 printf("*** Unknown option %s\n", argv[op]);
321 printf("Usage: pcretest [-d] [-i] [-p] [-s] [-t] [<input> [<output>]]\n");
322 printf(" -d debug: show compiled code; implies -i\n"
323 " -i show information about compiled pattern\n"
324 " -p use POSIX interface\n"
325 " -s output store information\n"
326 " -t time compilation and execution\n");
327 return 1;
328 }
329 op++;
330 argc--;
331 }
332
333 /* Sort out the input and output files */
334
335 if (argc > 1)
336 {
337 infile = fopen(argv[op], "r");
338 if (infile == NULL)
339 {
340 printf("** Failed to open %s\n", argv[op]);
341 return 1;
342 }
343 }
344
345 if (argc > 2)
346 {
347 outfile = fopen(argv[op+1], "w");
348 if (outfile == NULL)
349 {
350 printf("** Failed to open %s\n", argv[op+1]);
351 return 1;
352 }
353 }
354
355 /* Set alternative malloc function */
356
357 pcre_malloc = new_malloc;
358
359 /* Heading line, then prompt for first regex if stdin */
360
361 fprintf(outfile, "PCRE version %s\n\n", pcre_version());
362
363 /* Main loop */
364
365 while (!done)
366 {
367 pcre *re = NULL;
368 pcre_extra *extra = NULL;
369 regex_t preg;
370 const char *error;
371 unsigned char *p, *pp, *ppp;
372 unsigned const char *tables = NULL;
373 int do_study = 0;
374 int do_debug = debug;
375 int do_showinfo = showinfo;
376 int do_posix = 0;
377 int erroroffset, len, delimiter;
378
379 if (infile == stdin) printf(" re> ");
380 if (fgets((char *)buffer, sizeof(buffer), infile) == NULL) break;
381 if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
382
383 p = buffer;
384 while (isspace(*p)) p++;
385 if (*p == 0) continue;
386
387 /* Get the delimiter and seek the end of the pattern; if is isn't
388 complete, read more. */
389
390 delimiter = *p++;
391
392 if (isalnum(delimiter) || delimiter == '\\')
393 {
394 fprintf(outfile, "** Delimiter must not be alphameric or \\\n");
395 goto SKIP_DATA;
396 }
397
398 pp = p;
399
400 for(;;)
401 {
402 while (*pp != 0)
403 {
404 if (*pp == '\\' && pp[1] != 0) pp++;
405 else if (*pp == delimiter) break;
406 pp++;
407 }
408 if (*pp != 0) break;
409
410 len = sizeof(buffer) - (pp - buffer);
411 if (len < 256)
412 {
413 fprintf(outfile, "** Expression too long - missing delimiter?\n");
414 goto SKIP_DATA;
415 }
416
417 if (infile == stdin) printf(" > ");
418 if (fgets((char *)pp, len, infile) == NULL)
419 {
420 fprintf(outfile, "** Unexpected EOF\n");
421 done = 1;
422 goto CONTINUE;
423 }
424 if (infile != stdin) fprintf(outfile, "%s", (char *)pp);
425 }
426
427 /* If the first character after the delimiter is backslash, make
428 the pattern end with backslash. This is purely to provide a way
429 of testing for the error message when a pattern ends with backslash. */
430
431 if (pp[1] == '\\') *pp++ = '\\';
432
433 /* Terminate the pattern at the delimiter */
434
435 *pp++ = 0;
436
437 /* Look for options after final delimiter */
438
439 options = 0;
440 study_options = 0;
441 log_store = showstore; /* default from command line */
442
443 while (*pp != 0)
444 {
445 switch (*pp++)
446 {
447 case 'i': options |= PCRE_CASELESS; break;
448 case 'm': options |= PCRE_MULTILINE; break;
449 case 's': options |= PCRE_DOTALL; break;
450 case 'x': options |= PCRE_EXTENDED; break;
451
452 case 'A': options |= PCRE_ANCHORED; break;
453 case 'D': do_debug = do_showinfo = 1; break;
454 case 'E': options |= PCRE_DOLLAR_ENDONLY; break;
455 case 'I': do_showinfo = 1; break;
456 case 'M': log_store = 1; break;
457 case 'P': do_posix = 1; break;
458 case 'S': do_study = 1; break;
459 case 'U': options |= PCRE_UNGREEDY; break;
460 case 'X': options |= PCRE_EXTRA; break;
461
462 case 'L':
463 ppp = pp;
464 while (*ppp != '\n' && *ppp != ' ') ppp++;
465 *ppp = 0;
466 if (setlocale(LC_CTYPE, (const char *)pp) == NULL)
467 {
468 fprintf(outfile, "** Failed to set locale \"%s\"\n", pp);
469 goto SKIP_DATA;
470 }
471 tables = pcre_maketables();
472 pp = ppp;
473 break;
474
475 case '\n': case ' ': break;
476 default:
477 fprintf(outfile, "** Unknown option '%c'\n", pp[-1]);
478 goto SKIP_DATA;
479 }
480 }
481
482 /* Handle compiling via the POSIX interface, which doesn't support the
483 timing, showing, or debugging options, nor the ability to pass over
484 local character tables. */
485
486 if (posix || do_posix)
487 {
488 int rc;
489 int cflags = 0;
490 if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE;
491 if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE;
492 rc = regcomp(&preg, (char *)p, cflags);
493
494 /* Compilation failed; go back for another re, skipping to blank line
495 if non-interactive. */
496
497 if (rc != 0)
498 {
499 (void)regerror(rc, &preg, (char *)buffer, sizeof(buffer));
500 fprintf(outfile, "Failed: POSIX code %d: %s\n", rc, buffer);
501 goto SKIP_DATA;
502 }
503 }
504
505 /* Handle compiling via the native interface */
506
507 else
508 {
509 if (timeit)
510 {
511 register int i;
512 clock_t time_taken;
513 clock_t start_time = clock();
514 for (i = 0; i < LOOPREPEAT; i++)
515 {
516 re = pcre_compile((char *)p, options, &error, &erroroffset, tables);
517 if (re != NULL) free(re);
518 }
519 time_taken = clock() - start_time;
520 fprintf(outfile, "Compile time %.3f milliseconds\n",
521 ((double)time_taken * 1000.0) /
522 ((double)LOOPREPEAT * (double)CLOCKS_PER_SEC));
523 }
524
525 re = pcre_compile((char *)p, options, &error, &erroroffset, tables);
526
527 /* Compilation failed; go back for another re, skipping to blank line
528 if non-interactive. */
529
530 if (re == NULL)
531 {
532 fprintf(outfile, "Failed: %s at offset %d\n", error, erroroffset);
533 SKIP_DATA:
534 if (infile != stdin)
535 {
536 for (;;)
537 {
538 if (fgets((char *)buffer, sizeof(buffer), infile) == NULL)
539 {
540 done = 1;
541 goto CONTINUE;
542 }
543 len = (int)strlen((char *)buffer);
544 while (len > 0 && isspace(buffer[len-1])) len--;
545 if (len == 0) break;
546 }
547 fprintf(outfile, "\n");
548 }
549 goto CONTINUE;
550 }
551
552 /* Compilation succeeded; print data if required */
553
554 if (do_showinfo)
555 {
556 int first_char, count;
557
558 if (do_debug) print_internals(re, outfile);
559
560 count = pcre_info(re, &options, &first_char);
561 if (count < 0) fprintf(outfile,
562 "Error %d while reading info\n", count);
563 else
564 {
565 fprintf(outfile, "Identifying subpattern count = %d\n", count);
566 if (options == 0) fprintf(outfile, "No options\n");
567 else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s\n",
568 ((options & PCRE_ANCHORED) != 0)? " anchored" : "",
569 ((options & PCRE_CASELESS) != 0)? " caseless" : "",
570 ((options & PCRE_EXTENDED) != 0)? " extended" : "",
571 ((options & PCRE_MULTILINE) != 0)? " multiline" : "",
572 ((options & PCRE_DOTALL) != 0)? " dotall" : "",
573 ((options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",
574 ((options & PCRE_EXTRA) != 0)? " extra" : "",
575 ((options & PCRE_UNGREEDY) != 0)? " ungreedy" : "");
576 if (first_char == -1)
577 {
578 fprintf(outfile, "First char at start or follows \\n\n");
579 }
580 else if (first_char < 0)
581 {
582 fprintf(outfile, "No first char\n");
583 }
584 else
585 {
586 if (isprint(first_char))
587 fprintf(outfile, "First char = \'%c\'\n", first_char);
588 else
589 fprintf(outfile, "First char = %d\n", first_char);
590 }
591 }
592 }
593
594 /* If /S was present, study the regexp to generate additional info to
595 help with the matching. */
596
597 if (do_study)
598 {
599 if (timeit)
600 {
601 register int i;
602 clock_t time_taken;
603 clock_t start_time = clock();
604 for (i = 0; i < LOOPREPEAT; i++)
605 extra = pcre_study(re, study_options, &error);
606 time_taken = clock() - start_time;
607 if (extra != NULL) free(extra);
608 fprintf(outfile, " Study time %.3f milliseconds\n",
609 ((double)time_taken * 1000.0)/
610 ((double)LOOPREPEAT * (double)CLOCKS_PER_SEC));
611 }
612
613 extra = pcre_study(re, study_options, &error);
614 if (error != NULL)
615 fprintf(outfile, "Failed to study: %s\n", error);
616 else if (extra == NULL)
617 fprintf(outfile, "Study returned NULL\n");
618
619 /* This looks at internal information. A bit kludgy to do it this
620 way, but it is useful for testing. */
621
622 else if (do_showinfo)
623 {
624 real_pcre_extra *xx = (real_pcre_extra *)extra;
625 if ((xx->options & PCRE_STUDY_MAPPED) == 0)
626 fprintf(outfile, "No starting character set\n");
627 else
628 {
629 int i;
630 int c = 24;
631 fprintf(outfile, "Starting character set: ");
632 for (i = 0; i < 256; i++)
633 {
634 if ((xx->start_bits[i/8] & (1<<(i%8))) != 0)
635 {
636 if (c > 75)
637 {
638 fprintf(outfile, "\n ");
639 c = 2;
640 }
641 if (isprint(i) && i != ' ')
642 {
643 fprintf(outfile, "%c ", i);
644 c += 2;
645 }
646 else
647 {
648 fprintf(outfile, "\\x%02x ", i);
649 c += 5;
650 }
651 }
652 }
653 fprintf(outfile, "\n");
654 }
655 }
656 }
657 }
658
659 /* Read data lines and test them */
660
661 for (;;)
662 {
663 unsigned char *q;
664 int count, c;
665 int copystrings = 0;
666 int getstrings = 0;
667 int getlist = 0;
668 int offsets[45];
669 int size_offsets = sizeof(offsets)/sizeof(int);
670
671 options = 0;
672
673 if (infile == stdin) printf(" data> ");
674 if (fgets((char *)buffer, sizeof(buffer), infile) == NULL)
675 {
676 done = 1;
677 goto CONTINUE;
678 }
679 if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
680
681 len = (int)strlen((char *)buffer);
682 while (len > 0 && isspace(buffer[len-1])) len--;
683 buffer[len] = 0;
684 if (len == 0) break;
685
686 p = buffer;
687 while (isspace(*p)) p++;
688
689 q = dbuffer;
690 while ((c = *p++) != 0)
691 {
692 int i = 0;
693 int n = 0;
694 if (c == '\\') switch ((c = *p++))
695 {
696 case 'a': c = 7; break;
697 case 'b': c = '\b'; break;
698 case 'e': c = 27; break;
699 case 'f': c = '\f'; break;
700 case 'n': c = '\n'; break;
701 case 'r': c = '\r'; break;
702 case 't': c = '\t'; break;
703 case 'v': c = '\v'; break;
704
705 case '0': case '1': case '2': case '3':
706 case '4': case '5': case '6': case '7':
707 c -= '0';
708 while (i++ < 2 && isdigit(*p) && *p != '8' && *p != '9')
709 c = c * 8 + *p++ - '0';
710 break;
711
712 case 'x':
713 c = 0;
714 while (i++ < 2 && isxdigit(*p))
715 {
716 c = c * 16 + tolower(*p) - ((isdigit(*p))? '0' : 'W');
717 p++;
718 }
719 break;
720
721 case 0: /* Allows for an empty line */
722 p--;
723 continue;
724
725 case 'A': /* Option setting */
726 options |= PCRE_ANCHORED;
727 continue;
728
729 case 'B':
730 options |= PCRE_NOTBOL;
731 continue;
732
733 case 'C':
734 while(isdigit(*p)) n = n * 10 + *p++ - '0';
735 copystrings |= 1 << n;
736 continue;
737
738 case 'G':
739 while(isdigit(*p)) n = n * 10 + *p++ - '0';
740 getstrings |= 1 << n;
741 continue;
742
743 case 'L':
744 getlist = 1;
745 continue;
746
747 case 'O':
748 while(isdigit(*p)) n = n * 10 + *p++ - '0';
749 if (n <= (int)(sizeof(offsets)/sizeof(int))) size_offsets = n;
750 continue;
751
752 case 'Z':
753 options |= PCRE_NOTEOL;
754 continue;
755 }
756 *q++ = c;
757 }
758 *q = 0;
759 len = q - dbuffer;
760
761 /* Handle matching via the POSIX interface, which does not
762 support timing. */
763
764 if (posix || do_posix)
765 {
766 int rc;
767 int eflags = 0;
768 regmatch_t pmatch[30];
769 if ((options & PCRE_NOTBOL) != 0) eflags |= REG_NOTBOL;
770 if ((options & PCRE_NOTEOL) != 0) eflags |= REG_NOTEOL;
771
772 rc = regexec(&preg, (char *)dbuffer, sizeof(pmatch)/sizeof(regmatch_t),
773 pmatch, eflags);
774
775 if (rc != 0)
776 {
777 (void)regerror(rc, &preg, (char *)buffer, sizeof(buffer));
778 fprintf(outfile, "No match: POSIX code %d: %s\n", rc, buffer);
779 }
780 else
781 {
782 size_t i;
783 for (i = 0; i < sizeof(pmatch)/sizeof(regmatch_t); i++)
784 {
785 if (pmatch[i].rm_so >= 0)
786 {
787 fprintf(outfile, "%2d: ", (int)i);
788 pchars(dbuffer + pmatch[i].rm_so,
789 pmatch[i].rm_eo - pmatch[i].rm_so);
790 fprintf(outfile, "\n");
791 }
792 }
793 }
794 }
795
796 /* Handle matching via the native interface */
797
798 else
799 {
800 if (timeit)
801 {
802 register int i;
803 clock_t time_taken;
804 clock_t start_time = clock();
805 for (i = 0; i < LOOPREPEAT; i++)
806 count = pcre_exec(re, extra, (char *)dbuffer, len, options, offsets,
807 size_offsets);
808 time_taken = clock() - start_time;
809 fprintf(outfile, "Execute time %.3f milliseconds\n",
810 ((double)time_taken * 1000.0)/
811 ((double)LOOPREPEAT * (double)CLOCKS_PER_SEC));
812 }
813
814 count = pcre_exec(re, extra, (char *)dbuffer, len, options, offsets,
815 size_offsets);
816
817 if (count == 0)
818 {
819 fprintf(outfile, "Matched, but too many substrings\n");
820 count = size_offsets/3;
821 }
822
823 if (count >= 0)
824 {
825 int i;
826 for (i = 0; i < count * 2; i += 2)
827 {
828 if (offsets[i] < 0)
829 fprintf(outfile, "%2d: <unset>\n", i/2);
830 else
831 {
832 fprintf(outfile, "%2d: ", i/2);
833 pchars(dbuffer + offsets[i], offsets[i+1] - offsets[i]);
834 fprintf(outfile, "\n");
835 }
836 }
837
838 for (i = 0; i < 32; i++)
839 {
840 if ((copystrings & (1 << i)) != 0)
841 {
842 char buffer[16];
843 int rc = pcre_copy_substring((char *)dbuffer, offsets, count,
844 i, buffer, sizeof(buffer));
845 if (rc < 0)
846 fprintf(outfile, "copy substring %d failed %d\n", i, rc);
847 else
848 fprintf(outfile, "%2dC %s (%d)\n", i, buffer, rc);
849 }
850 }
851
852 for (i = 0; i < 32; i++)
853 {
854 if ((getstrings & (1 << i)) != 0)
855 {
856 const char *substring;
857 int rc = pcre_get_substring((char *)dbuffer, offsets, count,
858 i, &substring);
859 if (rc < 0)
860 fprintf(outfile, "get substring %d failed %d\n", i, rc);
861 else
862 {
863 fprintf(outfile, "%2dG %s (%d)\n", i, substring, rc);
864 free((void *)substring);
865 }
866 }
867 }
868
869 if (getlist)
870 {
871 const char **stringlist;
872 int rc = pcre_get_substring_list((char *)dbuffer, offsets, count,
873 &stringlist);
874 if (rc < 0)
875 fprintf(outfile, "get substring list failed %d\n", rc);
876 else
877 {
878 for (i = 0; i < count; i++)
879 fprintf(outfile, "%2dL %s\n", i, stringlist[i]);
880 if (stringlist[i] != NULL)
881 fprintf(outfile, "string list not terminated by NULL\n");
882 free((void *)stringlist);
883 }
884 }
885
886 }
887 else
888 {
889 if (count == -1) fprintf(outfile, "No match\n");
890 else fprintf(outfile, "Error %d\n", count);
891 }
892 }
893 }
894
895 CONTINUE:
896 if (posix || do_posix) regfree(&preg);
897 if (re != NULL) free(re);
898 if (extra != NULL) free(extra);
899 if (tables != NULL)
900 {
901 free((void *)tables);
902 setlocale(LC_CTYPE, "C");
903 }
904 }
905
906 fprintf(outfile, "\n");
907 return 0;
908 }
909
910 /* End */

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12