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

Contents of /code/trunk/pcretest.c

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12