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

Contents of /code/trunk/pcretest.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 nigel 3 /*************************************************
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 nigel 23 #define LOOPREPEAT 10000
25 nigel 3
26 nigel 23
27 nigel 3 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 nigel 7 static const char *OP_names[] = {
36     "End", "\\A", "\\B", "\\b", "\\D", "\\d",
37 nigel 23 "\\S", "\\s", "\\W", "\\w", "\\Z", "\\z",
38     "Opt", "^", "$", "Any", "chars", "not",
39 nigel 3 "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
40     "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
41     "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
42     "*", "*?", "+", "+?", "?", "??", "{", "{",
43 nigel 23 "class", "Ref",
44     "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not",
45     "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cref",
46 nigel 3 "Brazero", "Braminzero", "Bra"
47     };
48    
49    
50 nigel 23 static void print_internals(pcre *re, FILE *outfile)
51 nigel 3 {
52     unsigned char *code = ((real_pcre *)re)->code;
53    
54 nigel 23 fprintf(outfile, "------------------------------------------------------------------\n");
55 nigel 3
56     for(;;)
57     {
58     int c;
59     int charlength;
60    
61 nigel 23 fprintf(outfile, "%3d ", (int)(code - ((real_pcre *)re)->code));
62 nigel 3
63     if (*code >= OP_BRA)
64     {
65 nigel 23 fprintf(outfile, "%3d Bra %d", (code[1] << 8) + code[2], *code - OP_BRA);
66 nigel 3 code += 2;
67     }
68    
69     else switch(*code)
70     {
71     case OP_END:
72 nigel 23 fprintf(outfile, " %s\n", OP_names[*code]);
73     fprintf(outfile, "------------------------------------------------------------------\n");
74 nigel 3 return;
75    
76 nigel 23 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 nigel 3 case OP_CHARS:
92     charlength = *(++code);
93 nigel 23 fprintf(outfile, "%3d ", charlength);
94 nigel 3 while (charlength-- > 0)
95 nigel 23 if (isprint(c = *(++code))) fprintf(outfile, "%c", c);
96     else fprintf(outfile, "\\x%02x", c);
97 nigel 3 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 nigel 23 case OP_ASSERTBACK:
106     case OP_ASSERTBACK_NOT:
107 nigel 3 case OP_ONCE:
108 nigel 23 fprintf(outfile, "%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
109 nigel 3 code += 2;
110     break;
111    
112 nigel 23 case OP_REVERSE:
113     fprintf(outfile, "%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
114     code += 2;
115     break;
116    
117 nigel 3 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 nigel 23 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 nigel 3 break;
135    
136     case OP_EXACT:
137     case OP_UPTO:
138     case OP_MINUPTO:
139 nigel 23 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 nigel 3 code += 3;
145     break;
146    
147     case OP_TYPEEXACT:
148     case OP_TYPEUPTO:
149     case OP_TYPEMINUPTO:
150 nigel 23 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 nigel 3 code += 3;
155     break;
156    
157     case OP_NOT:
158 nigel 23 if (isprint(c = *(++code))) fprintf(outfile, " [^%c]", c);
159     else fprintf(outfile, " [^\\x%02x]", c);
160 nigel 3 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 nigel 23 if (isprint(c = code[1])) fprintf(outfile, " [^%c]", c);
169     else fprintf(outfile, " [^\\x%02x]", c);
170     fprintf(outfile, "%s", OP_names[*code++]);
171 nigel 3 break;
172    
173     case OP_NOTEXACT:
174     case OP_NOTUPTO:
175     case OP_NOTMINUPTO:
176 nigel 23 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 nigel 3 code += 3;
182     break;
183    
184     case OP_REF:
185 nigel 23 fprintf(outfile, " \\%d", *(++code));
186 nigel 9 code++;
187     goto CLASS_REF_REPEAT;
188 nigel 3
189     case OP_CLASS:
190     {
191     int i, min, max;
192 nigel 23 code++;
193     fprintf(outfile, " [");
194 nigel 3
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 nigel 23 if (i == '-' || i == ']') fprintf(outfile, "\\");
203     if (isprint(i)) fprintf(outfile, "%c", i); else fprintf(outfile, "\\x%02x", i);
204 nigel 3 if (--j > i)
205     {
206 nigel 23 fprintf(outfile, "-");
207     if (j == '-' || j == ']') fprintf(outfile, "\\");
208     if (isprint(j)) fprintf(outfile, "%c", j); else fprintf(outfile, "\\x%02x", j);
209 nigel 3 }
210     i = j;
211     }
212     }
213 nigel 23 fprintf(outfile, "]");
214 nigel 3 code += 32;
215    
216 nigel 9 CLASS_REF_REPEAT:
217    
218 nigel 3 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 nigel 23 fprintf(outfile, "%s", OP_names[*code]);
227 nigel 3 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 nigel 23 if (max == 0) fprintf(outfile, "{%d,}", min);
234     else fprintf(outfile, "{%d,%d}", min, max);
235     if (*code == OP_CRMINRANGE) fprintf(outfile, "?");
236 nigel 3 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 nigel 23 fprintf(outfile, " %s", OP_names[*code]);
249 nigel 3 break;
250     }
251    
252     code++;
253 nigel 23 fprintf(outfile, "\n");
254 nigel 3 }
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 nigel 11 int done = 0;
297 nigel 3 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 nigel 23 /* Heading line, then prompt for first regex if stdin */
349 nigel 3
350     fprintf(outfile, "PCRE version %s\n\n", pcre_version());
351    
352     /* Main loop */
353    
354 nigel 11 while (!done)
355 nigel 3 {
356     pcre *re = NULL;
357     pcre_extra *extra = NULL;
358     regex_t preg;
359 nigel 7 const char *error;
360 nigel 3 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 nigel 23 if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
369 nigel 3
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 nigel 11 done = 1;
404     goto CONTINUE;
405 nigel 3 }
406 nigel 23 if (infile != stdin) fprintf(outfile, "%s", (char *)pp);
407 nigel 3 }
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 nigel 19 case 'U': options |= PCRE_UNGREEDY; break;
431 nigel 3 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 nigel 11 /* Handle compiling via the POSIX interface, which doesn't support the
440 nigel 3 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 nigel 23 for (i = 0; i < LOOPREPEAT; i++)
471 nigel 3 {
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 nigel 11 {
495     done = 1;
496     goto CONTINUE;
497     }
498 nigel 3 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 nigel 23 if (debug || do_debug) print_internals(re, outfile);
514 nigel 3
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 nigel 19 else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s\n",
523 nigel 3 ((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 nigel 19 ((options & PCRE_EXTRA) != 0)? " extra" : "",
530     ((options & PCRE_UNGREEDY) != 0)? " ungreedy" : "");
531 nigel 3 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 nigel 23 for (i = 0; i < LOOPREPEAT; i++)
560 nigel 3 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 nigel 9 unsigned char *q;
618 nigel 3 int count, c;
619 nigel 23 int offsets[45];
620 nigel 3 int size_offsets = sizeof(offsets)/sizeof(int);
621    
622     options = 0;
623    
624     if (infile == stdin) printf(" data> ");
625 nigel 11 if (fgets((char *)buffer, sizeof(buffer), infile) == NULL)
626     {
627     done = 1;
628     goto CONTINUE;
629     }
630 nigel 23 if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
631 nigel 3
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 nigel 9 q = dbuffer;
641 nigel 3 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 nigel 9 if (n <= (int)(sizeof(offsets)/sizeof(int))) size_offsets = n;
687 nigel 3 continue;
688    
689     case 'Z':
690     options |= PCRE_NOTEOL;
691     continue;
692     }
693 nigel 9 *q++ = c;
694 nigel 3 }
695 nigel 9 *q = 0;
696     len = q - dbuffer;
697 nigel 3
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 nigel 7 size_t i;
720 nigel 3 for (i = 0; i < sizeof(pmatch)/sizeof(regmatch_t); i++)
721     {
722     if (pmatch[i].rm_so >= 0)
723     {
724 nigel 23 fprintf(outfile, "%2d: ", (int)i);
725 nigel 3 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 nigel 23 count = size_offsets/3;
757 nigel 3 }
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 nigel 11 CONTINUE:
784 nigel 3 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