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

Contents of /code/trunk/pcretest.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 343 - (hide annotations) (download)
Mon Apr 21 16:30:37 2008 UTC (6 years, 4 months ago) by ph10
File MIME type: text/plain
File size: 71572 byte(s)
Fixes to pcretest for readline support on Windows.

1 nigel 3 /*************************************************
2     * PCRE testing program *
3     *************************************************/
4    
5 nigel 63 /* This program was hacked up as a tester for PCRE. I really should have
6     written it more tidily in the first place. Will I ever learn? It has grown and
7 nigel 77 been extended and consequently is now rather, er, *very* untidy in places.
8 nigel 63
9 nigel 75 -----------------------------------------------------------------------------
10     Redistribution and use in source and binary forms, with or without
11     modification, are permitted provided that the following conditions are met:
12    
13     * Redistributions of source code must retain the above copyright notice,
14     this list of conditions and the following disclaimer.
15    
16     * Redistributions in binary form must reproduce the above copyright
17     notice, this list of conditions and the following disclaimer in the
18     documentation and/or other materials provided with the distribution.
19    
20     * Neither the name of the University of Cambridge nor the names of its
21     contributors may be used to endorse or promote products derived from
22     this software without specific prior written permission.
23    
24     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27     ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34     POSSIBILITY OF SUCH DAMAGE.
35     -----------------------------------------------------------------------------
36     */
37    
38    
39 ph10 200 #ifdef HAVE_CONFIG_H
40 ph10 236 #include "config.h"
41 ph10 200 #endif
42 ph10 199
43 nigel 3 #include <ctype.h>
44     #include <stdio.h>
45     #include <string.h>
46     #include <stdlib.h>
47     #include <time.h>
48 nigel 25 #include <locale.h>
49 nigel 75 #include <errno.h>
50 nigel 3
51 ph10 287 #ifdef SUPPORT_LIBREADLINE
52 ph10 343 #ifdef HAVE_UNISTD_H
53 ph10 287 #include <unistd.h>
54 ph10 343 #endif
55 ph10 287 #include <readline/readline.h>
56     #include <readline/history.h>
57     #endif
58 nigel 93
59 ph10 287
60 nigel 93 /* A number of things vary for Windows builds. Originally, pcretest opened its
61     input and output without "b"; then I was told that "b" was needed in some
62     environments, so it was added for release 5.0 to both the input and output. (It
63     makes no difference on Unix-like systems.) Later I was told that it is wrong
64     for the input on Windows. I've now abstracted the modes into two macros that
65     are set here, to make it easier to fiddle with them, and removed "b" from the
66     input mode under Windows. */
67    
68     #if defined(_WIN32) || defined(WIN32)
69     #include <io.h> /* For _setmode() */
70     #include <fcntl.h> /* For _O_BINARY */
71     #define INPUT_MODE "r"
72     #define OUTPUT_MODE "wb"
73    
74 ph10 343 #define isatty _isatty /* This is what Windows calls them, I'm told */
75     #define fileno _fileno
76    
77 nigel 93 #else
78     #include <sys/time.h> /* These two includes are needed */
79     #include <sys/resource.h> /* for setrlimit(). */
80     #define INPUT_MODE "rb"
81     #define OUTPUT_MODE "wb"
82 nigel 91 #endif
83    
84 nigel 93
85 ph10 145 /* We have to include pcre_internal.h because we need the internal info for
86     displaying the results of pcre_study() and we also need to know about the
87     internal macros, structures, and other internal data values; pcretest has
88     "inside information" compared to a program that strictly follows the PCRE API.
89 nigel 37
90 ph10 145 Although pcre_internal.h does itself include pcre.h, we explicitly include it
91     here before pcre_internal.h so that the PCRE_EXP_xxx macros get set
92     appropriately for an application, not for building PCRE. */
93 nigel 77
94 ph10 145 #include "pcre.h"
95 nigel 77 #include "pcre_internal.h"
96    
97 nigel 85 /* We need access to the data tables that PCRE uses. So as not to have to keep
98     two copies, we include the source file here, changing the names of the external
99     symbols to prevent clashes. */
100 nigel 77
101 nigel 85 #define _pcre_utf8_table1 utf8_table1
102     #define _pcre_utf8_table1_size utf8_table1_size
103     #define _pcre_utf8_table2 utf8_table2
104     #define _pcre_utf8_table3 utf8_table3
105     #define _pcre_utf8_table4 utf8_table4
106     #define _pcre_utt utt
107     #define _pcre_utt_size utt_size
108 ph10 240 #define _pcre_utt_names utt_names
109 nigel 85 #define _pcre_OP_lengths OP_lengths
110    
111     #include "pcre_tables.c"
112    
113     /* We also need the pcre_printint() function for printing out compiled
114     patterns. This function is in a separate file so that it can be included in
115 nigel 93 pcre_compile.c when that module is compiled with debugging enabled.
116 nigel 85
117 nigel 93 The definition of the macro PRINTABLE, which determines whether to print an
118     output character as-is or as a hex value when showing compiled patterns, is
119     contained in this file. We uses it here also, in cases when the locale has not
120     been explicitly changed, so as to get consistent output from systems that
121     differ in their output from isprint() even in the "C" locale. */
122    
123 nigel 85 #include "pcre_printint.src"
124    
125 nigel 93 #define PRINTHEX(c) (locale_set? isprint(c) : PRINTABLE(c))
126 nigel 85
127 nigel 93
128 nigel 37 /* It is possible to compile this test program without including support for
129     testing the POSIX interface, though this is not available via the standard
130     Makefile. */
131    
132     #if !defined NOPOSIX
133 nigel 3 #include "pcreposix.h"
134 nigel 37 #endif
135 nigel 3
136 ph10 107 /* It is also possible, for the benefit of the version currently imported into
137     Exim, to build pcretest without support for UTF8 (define NOUTF8), without the
138     interface to the DFA matcher (NODFA), and without the doublecheck of the old
139     "info" function (define NOINFOCHECK). In fact, we automatically cut out the
140     UTF8 support if PCRE is built without it. */
141 nigel 79
142 ph10 107 #ifndef SUPPORT_UTF8
143     #ifndef NOUTF8
144     #define NOUTF8
145     #endif
146     #endif
147 nigel 79
148 ph10 107
149 nigel 85 /* Other parameters */
150    
151 nigel 3 #ifndef CLOCKS_PER_SEC
152     #ifdef CLK_TCK
153     #define CLOCKS_PER_SEC CLK_TCK
154     #else
155     #define CLOCKS_PER_SEC 100
156     #endif
157     #endif
158    
159 nigel 93 /* This is the default loop count for timing. */
160    
161 nigel 75 #define LOOPREPEAT 500000
162 nigel 3
163 nigel 85 /* Static variables */
164    
165 nigel 3 static FILE *outfile;
166     static int log_store = 0;
167 nigel 63 static int callout_count;
168     static int callout_extra;
169     static int callout_fail_count;
170     static int callout_fail_id;
171 ph10 210 static int debug_lengths;
172 nigel 63 static int first_callout;
173 nigel 93 static int locale_set = 0;
174 nigel 73 static int show_malloc;
175 nigel 67 static int use_utf8;
176 nigel 43 static size_t gotten_store;
177 nigel 3
178 nigel 91 /* The buffers grow automatically if very long input lines are encountered. */
179    
180     static int buffer_size = 50000;
181     static uschar *buffer = NULL;
182     static uschar *dbuffer = NULL;
183 nigel 75 static uschar *pbuffer = NULL;
184 nigel 3
185 nigel 75
186 nigel 49
187     /*************************************************
188 nigel 91 * Read or extend an input line *
189     *************************************************/
190    
191     /* Input lines are read into buffer, but both patterns and data lines can be
192     continued over multiple input lines. In addition, if the buffer fills up, we
193     want to automatically expand it so as to be able to handle extremely large
194     lines that are needed for certain stress tests. When the input buffer is
195     expanded, the other two buffers must also be expanded likewise, and the
196     contents of pbuffer, which are a copy of the input for callouts, must be
197     preserved (for when expansion happens for a data line). This is not the most
198     optimal way of handling this, but hey, this is just a test program!
199    
200     Arguments:
201     f the file to read
202     start where in buffer to start (this *must* be within buffer)
203 ph10 287 prompt for stdin or readline()
204 nigel 91
205     Returns: pointer to the start of new data
206     could be a copy of start, or could be moved
207     NULL if no data read and EOF reached
208     */
209    
210     static uschar *
211 ph10 287 extend_inputline(FILE *f, uschar *start, const char *prompt)
212 nigel 91 {
213     uschar *here = start;
214    
215     for (;;)
216     {
217     int rlen = buffer_size - (here - buffer);
218 nigel 93
219 nigel 91 if (rlen > 1000)
220     {
221     int dlen;
222 ph10 289
223 ph10 287 /* If libreadline support is required, use readline() to read a line if the
224     input is a terminal. Note that readline() removes the trailing newline, so
225     we must put it back again, to be compatible with fgets(). */
226 ph10 289
227 ph10 287 #ifdef SUPPORT_LIBREADLINE
228     if (isatty(fileno(f)))
229     {
230 ph10 289 size_t len;
231 ph10 287 char *s = readline(prompt);
232     if (s == NULL) return (here == start)? NULL : start;
233     len = strlen(s);
234 ph10 289 if (len > 0) add_history(s);
235 ph10 287 if (len > rlen - 1) len = rlen - 1;
236     memcpy(here, s, len);
237     here[len] = '\n';
238 ph10 289 here[len+1] = 0;
239     free(s);
240 ph10 287 }
241 ph10 289 else
242     #endif
243    
244 ph10 287 /* Read the next line by normal means, prompting if the file is stdin. */
245 ph10 289
246 ph10 287 {
247 ph10 289 if (f == stdin) printf(prompt);
248 ph10 287 if (fgets((char *)here, rlen, f) == NULL)
249     return (here == start)? NULL : start;
250 ph10 289 }
251    
252 nigel 91 dlen = (int)strlen((char *)here);
253     if (dlen > 0 && here[dlen - 1] == '\n') return start;
254     here += dlen;
255     }
256    
257     else
258     {
259     int new_buffer_size = 2*buffer_size;
260     uschar *new_buffer = (unsigned char *)malloc(new_buffer_size);
261     uschar *new_dbuffer = (unsigned char *)malloc(new_buffer_size);
262     uschar *new_pbuffer = (unsigned char *)malloc(new_buffer_size);
263    
264     if (new_buffer == NULL || new_dbuffer == NULL || new_pbuffer == NULL)
265     {
266     fprintf(stderr, "pcretest: malloc(%d) failed\n", new_buffer_size);
267     exit(1);
268     }
269    
270     memcpy(new_buffer, buffer, buffer_size);
271     memcpy(new_pbuffer, pbuffer, buffer_size);
272    
273     buffer_size = new_buffer_size;
274    
275     start = new_buffer + (start - buffer);
276     here = new_buffer + (here - buffer);
277    
278     free(buffer);
279     free(dbuffer);
280     free(pbuffer);
281    
282     buffer = new_buffer;
283     dbuffer = new_dbuffer;
284     pbuffer = new_pbuffer;
285     }
286     }
287    
288     return NULL; /* Control never gets here */
289     }
290    
291    
292    
293    
294    
295    
296    
297     /*************************************************
298 nigel 63 * Read number from string *
299     *************************************************/
300    
301     /* We don't use strtoul() because SunOS4 doesn't have it. Rather than mess
302     around with conditional compilation, just do the job by hand. It is only used
303 nigel 93 for unpicking arguments, so just keep it simple.
304 nigel 63
305     Arguments:
306     str string to be converted
307     endptr where to put the end pointer
308    
309     Returns: the unsigned long
310     */
311    
312     static int
313     get_value(unsigned char *str, unsigned char **endptr)
314     {
315     int result = 0;
316     while(*str != 0 && isspace(*str)) str++;
317     while (isdigit(*str)) result = result * 10 + (int)(*str++ - '0');
318     *endptr = str;
319     return(result);
320     }
321    
322    
323    
324 nigel 49
325     /*************************************************
326     * Convert UTF-8 string to value *
327     *************************************************/
328    
329     /* This function takes one or more bytes that represents a UTF-8 character,
330     and returns the value of the character.
331    
332     Argument:
333 nigel 91 utf8bytes a pointer to the byte vector
334     vptr a pointer to an int to receive the value
335 nigel 49
336 nigel 91 Returns: > 0 => the number of bytes consumed
337     -6 to 0 => malformed UTF-8 character at offset = (-return)
338 nigel 49 */
339    
340 nigel 79 #if !defined NOUTF8
341    
342 nigel 67 static int
343 nigel 91 utf82ord(unsigned char *utf8bytes, int *vptr)
344 nigel 49 {
345 nigel 91 int c = *utf8bytes++;
346 nigel 49 int d = c;
347     int i, j, s;
348    
349     for (i = -1; i < 6; i++) /* i is number of additional bytes */
350     {
351     if ((d & 0x80) == 0) break;
352     d <<= 1;
353     }
354    
355     if (i == -1) { *vptr = c; return 1; } /* ascii character */
356     if (i == 0 || i == 6) return 0; /* invalid UTF-8 */
357    
358     /* i now has a value in the range 1-5 */
359    
360 nigel 59 s = 6*i;
361 nigel 85 d = (c & utf8_table3[i]) << s;
362 nigel 49
363     for (j = 0; j < i; j++)
364     {
365 nigel 91 c = *utf8bytes++;
366 nigel 49 if ((c & 0xc0) != 0x80) return -(j+1);
367 nigel 59 s -= 6;
368 nigel 49 d |= (c & 0x3f) << s;
369     }
370    
371     /* Check that encoding was the correct unique one */
372    
373 nigel 85 for (j = 0; j < utf8_table1_size; j++)
374     if (d <= utf8_table1[j]) break;
375 nigel 49 if (j != i) return -(i+1);
376    
377     /* Valid value */
378    
379     *vptr = d;
380     return i+1;
381     }
382    
383 nigel 79 #endif
384 nigel 49
385    
386 nigel 79
387 nigel 63 /*************************************************
388 nigel 85 * Convert character value to UTF-8 *
389     *************************************************/
390    
391     /* This function takes an integer value in the range 0 - 0x7fffffff
392     and encodes it as a UTF-8 character in 0 to 6 bytes.
393    
394     Arguments:
395     cvalue the character value
396 nigel 91 utf8bytes pointer to buffer for result - at least 6 bytes long
397 nigel 85
398     Returns: number of characters placed in the buffer
399     */
400    
401 nigel 93 #if !defined NOUTF8
402    
403 nigel 85 static int
404 nigel 91 ord2utf8(int cvalue, uschar *utf8bytes)
405 nigel 85 {
406     register int i, j;
407     for (i = 0; i < utf8_table1_size; i++)
408     if (cvalue <= utf8_table1[i]) break;
409 nigel 91 utf8bytes += i;
410 nigel 85 for (j = i; j > 0; j--)
411     {
412 nigel 91 *utf8bytes-- = 0x80 | (cvalue & 0x3f);
413 nigel 85 cvalue >>= 6;
414     }
415 nigel 91 *utf8bytes = utf8_table2[i] | cvalue;
416 nigel 85 return i + 1;
417     }
418    
419 nigel 93 #endif
420 nigel 85
421    
422 nigel 93
423 nigel 85 /*************************************************
424 nigel 63 * Print character string *
425     *************************************************/
426 nigel 49
427 nigel 63 /* Character string printing function. Must handle UTF-8 strings in utf8
428     mode. Yields number of characters printed. If handed a NULL file, just counts
429     chars without printing. */
430 nigel 49
431 nigel 63 static int pchars(unsigned char *p, int length, FILE *f)
432 nigel 3 {
433 nigel 85 int c = 0;
434 nigel 63 int yield = 0;
435 nigel 3
436 nigel 63 while (length-- > 0)
437 nigel 3 {
438 nigel 79 #if !defined NOUTF8
439 nigel 67 if (use_utf8)
440 nigel 63 {
441     int rc = utf82ord(p, &c);
442 nigel 3
443 nigel 63 if (rc > 0 && rc <= length + 1) /* Mustn't run over the end */
444     {
445     length -= rc - 1;
446     p += rc;
447 nigel 93 if (PRINTHEX(c))
448 nigel 63 {
449     if (f != NULL) fprintf(f, "%c", c);
450     yield++;
451     }
452     else
453     {
454 nigel 93 int n = 4;
455     if (f != NULL) fprintf(f, "\\x{%02x}", c);
456     yield += (n <= 0x000000ff)? 2 :
457     (n <= 0x00000fff)? 3 :
458     (n <= 0x0000ffff)? 4 :
459     (n <= 0x000fffff)? 5 : 6;
460 nigel 63 }
461     continue;
462     }
463     }
464 nigel 79 #endif
465 nigel 3
466 nigel 63 /* Not UTF-8, or malformed UTF-8 */
467    
468 nigel 93 c = *p++;
469     if (PRINTHEX(c))
470 nigel 3 {
471 nigel 63 if (f != NULL) fprintf(f, "%c", c);
472     yield++;
473 nigel 3 }
474 nigel 63 else
475 nigel 3 {
476 nigel 63 if (f != NULL) fprintf(f, "\\x%02x", c);
477     yield += 4;
478     }
479     }
480 nigel 3
481 nigel 63 return yield;
482     }
483 nigel 23
484 nigel 3
485 nigel 23
486 nigel 63 /*************************************************
487     * Callout function *
488     *************************************************/
489 nigel 3
490 nigel 63 /* Called from PCRE as a result of the (?C) item. We print out where we are in
491     the match. Yield zero unless more callouts than the fail count, or the callout
492     data is not zero. */
493 nigel 3
494 nigel 63 static int callout(pcre_callout_block *cb)
495     {
496     FILE *f = (first_callout | callout_extra)? outfile : NULL;
497 nigel 75 int i, pre_start, post_start, subject_length;
498 nigel 3
499 nigel 63 if (callout_extra)
500     {
501     fprintf(f, "Callout %d: last capture = %d\n",
502     cb->callout_number, cb->capture_last);
503 nigel 3
504 nigel 63 for (i = 0; i < cb->capture_top * 2; i += 2)
505     {
506     if (cb->offset_vector[i] < 0)
507     fprintf(f, "%2d: <unset>\n", i/2);
508     else
509     {
510     fprintf(f, "%2d: ", i/2);
511     (void)pchars((unsigned char *)cb->subject + cb->offset_vector[i],
512     cb->offset_vector[i+1] - cb->offset_vector[i], f);
513     fprintf(f, "\n");
514     }
515     }
516     }
517 nigel 3
518 nigel 63 /* Re-print the subject in canonical form, the first time or if giving full
519     datails. On subsequent calls in the same match, we use pchars just to find the
520     printed lengths of the substrings. */
521 nigel 3
522 nigel 63 if (f != NULL) fprintf(f, "--->");
523 nigel 3
524 nigel 63 pre_start = pchars((unsigned char *)cb->subject, cb->start_match, f);
525     post_start = pchars((unsigned char *)(cb->subject + cb->start_match),
526     cb->current_position - cb->start_match, f);
527 nigel 3
528 nigel 75 subject_length = pchars((unsigned char *)cb->subject, cb->subject_length, NULL);
529    
530 nigel 63 (void)pchars((unsigned char *)(cb->subject + cb->current_position),
531     cb->subject_length - cb->current_position, f);
532 nigel 3
533 nigel 63 if (f != NULL) fprintf(f, "\n");
534 nigel 9
535 nigel 63 /* Always print appropriate indicators, with callout number if not already
536 nigel 75 shown. For automatic callouts, show the pattern offset. */
537 nigel 3
538 nigel 75 if (cb->callout_number == 255)
539     {
540     fprintf(outfile, "%+3d ", cb->pattern_position);
541     if (cb->pattern_position > 99) fprintf(outfile, "\n ");
542     }
543     else
544     {
545     if (callout_extra) fprintf(outfile, " ");
546     else fprintf(outfile, "%3d ", cb->callout_number);
547     }
548 nigel 3
549 nigel 63 for (i = 0; i < pre_start; i++) fprintf(outfile, " ");
550     fprintf(outfile, "^");
551 nigel 3
552 nigel 63 if (post_start > 0)
553     {
554     for (i = 0; i < post_start - 1; i++) fprintf(outfile, " ");
555     fprintf(outfile, "^");
556 nigel 3 }
557    
558 nigel 75 for (i = 0; i < subject_length - pre_start - post_start + 4; i++)
559     fprintf(outfile, " ");
560    
561     fprintf(outfile, "%.*s", (cb->next_item_length == 0)? 1 : cb->next_item_length,
562     pbuffer + cb->pattern_position);
563    
564 nigel 63 fprintf(outfile, "\n");
565     first_callout = 0;
566 nigel 3
567 nigel 71 if (cb->callout_data != NULL)
568 nigel 49 {
569 nigel 71 int callout_data = *((int *)(cb->callout_data));
570     if (callout_data != 0)
571     {
572     fprintf(outfile, "Callout data = %d\n", callout_data);
573     return callout_data;
574     }
575 nigel 63 }
576 nigel 49
577 nigel 63 return (cb->callout_number != callout_fail_id)? 0 :
578     (++callout_count >= callout_fail_count)? 1 : 0;
579 nigel 3 }
580    
581    
582 nigel 63 /*************************************************
583 nigel 73 * Local malloc functions *
584 nigel 63 *************************************************/
585 nigel 3
586     /* Alternative malloc function, to test functionality and show the size of the
587     compiled re. */
588    
589     static void *new_malloc(size_t size)
590     {
591 nigel 73 void *block = malloc(size);
592 nigel 43 gotten_store = size;
593 nigel 73 if (show_malloc)
594 nigel 77 fprintf(outfile, "malloc %3d %p\n", (int)size, block);
595 nigel 73 return block;
596 nigel 3 }
597    
598 nigel 73 static void new_free(void *block)
599     {
600     if (show_malloc)
601     fprintf(outfile, "free %p\n", block);
602     free(block);
603     }
604 nigel 3
605    
606 nigel 73 /* For recursion malloc/free, to test stacking calls */
607    
608     static void *stack_malloc(size_t size)
609     {
610     void *block = malloc(size);
611     if (show_malloc)
612 nigel 77 fprintf(outfile, "stack_malloc %3d %p\n", (int)size, block);
613 nigel 73 return block;
614     }
615    
616     static void stack_free(void *block)
617     {
618     if (show_malloc)
619     fprintf(outfile, "stack_free %p\n", block);
620     free(block);
621     }
622    
623    
624 nigel 63 /*************************************************
625     * Call pcre_fullinfo() *
626     *************************************************/
627 nigel 43
628     /* Get one piece of information from the pcre_fullinfo() function */
629    
630     static void new_info(pcre *re, pcre_extra *study, int option, void *ptr)
631     {
632     int rc;
633     if ((rc = pcre_fullinfo(re, study, option, ptr)) < 0)
634     fprintf(outfile, "Error %d from pcre_fullinfo(%d)\n", rc, option);
635     }
636    
637    
638    
639 nigel 63 /*************************************************
640 nigel 75 * Byte flipping function *
641     *************************************************/
642    
643 nigel 91 static unsigned long int
644     byteflip(unsigned long int value, int n)
645 nigel 75 {
646     if (n == 2) return ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8);
647     return ((value & 0x000000ff) << 24) |
648     ((value & 0x0000ff00) << 8) |
649     ((value & 0x00ff0000) >> 8) |
650     ((value & 0xff000000) >> 24);
651     }
652    
653    
654    
655    
656     /*************************************************
657 nigel 87 * Check match or recursion limit *
658     *************************************************/
659    
660     static int
661     check_match_limit(pcre *re, pcre_extra *extra, uschar *bptr, int len,
662     int start_offset, int options, int *use_offsets, int use_size_offsets,
663     int flag, unsigned long int *limit, int errnumber, const char *msg)
664     {
665     int count;
666     int min = 0;
667     int mid = 64;
668     int max = -1;
669    
670     extra->flags |= flag;
671    
672     for (;;)
673     {
674     *limit = mid;
675    
676     count = pcre_exec(re, extra, (char *)bptr, len, start_offset, options,
677     use_offsets, use_size_offsets);
678    
679     if (count == errnumber)
680     {
681     /* fprintf(outfile, "Testing %s limit = %d\n", msg, mid); */
682     min = mid;
683     mid = (mid == max - 1)? max : (max > 0)? (min + max)/2 : mid*2;
684     }
685    
686     else if (count >= 0 || count == PCRE_ERROR_NOMATCH ||
687     count == PCRE_ERROR_PARTIAL)
688     {
689     if (mid == min + 1)
690     {
691     fprintf(outfile, "Minimum %s limit = %d\n", msg, mid);
692     break;
693     }
694     /* fprintf(outfile, "Testing %s limit = %d\n", msg, mid); */
695     max = mid;
696     mid = (min + mid)/2;
697     }
698     else break; /* Some other error */
699     }
700    
701     extra->flags &= ~flag;
702     return count;
703     }
704    
705    
706    
707     /*************************************************
708 ph10 227 * Case-independent strncmp() function *
709     *************************************************/
710    
711     /*
712     Arguments:
713     s first string
714     t second string
715     n number of characters to compare
716    
717     Returns: < 0, = 0, or > 0, according to the comparison
718     */
719    
720     static int
721     strncmpic(uschar *s, uschar *t, int n)
722     {
723     while (n--)
724     {
725     int c = tolower(*s++) - tolower(*t++);
726     if (c) return c;
727     }
728     return 0;
729     }
730    
731    
732    
733     /*************************************************
734 nigel 91 * Check newline indicator *
735     *************************************************/
736    
737     /* This is used both at compile and run-time to check for <xxx> escapes, where
738 ph10 149 xxx is LF, CR, CRLF, ANYCRLF, or ANY. Print a message and return 0 if there is
739     no match.
740 nigel 91
741     Arguments:
742     p points after the leading '<'
743     f file for error message
744    
745     Returns: appropriate PCRE_NEWLINE_xxx flags, or 0
746     */
747    
748     static int
749     check_newline(uschar *p, FILE *f)
750     {
751 ph10 227 if (strncmpic(p, (uschar *)"cr>", 3) == 0) return PCRE_NEWLINE_CR;
752     if (strncmpic(p, (uschar *)"lf>", 3) == 0) return PCRE_NEWLINE_LF;
753     if (strncmpic(p, (uschar *)"crlf>", 5) == 0) return PCRE_NEWLINE_CRLF;
754     if (strncmpic(p, (uschar *)"anycrlf>", 8) == 0) return PCRE_NEWLINE_ANYCRLF;
755     if (strncmpic(p, (uschar *)"any>", 4) == 0) return PCRE_NEWLINE_ANY;
756 ph10 231 if (strncmpic(p, (uschar *)"bsr_anycrlf>", 12) == 0) return PCRE_BSR_ANYCRLF;
757     if (strncmpic(p, (uschar *)"bsr_unicode>", 12) == 0) return PCRE_BSR_UNICODE;
758 nigel 91 fprintf(f, "Unknown newline type at: <%s\n", p);
759     return 0;
760     }
761    
762    
763    
764     /*************************************************
765 nigel 93 * Usage function *
766     *************************************************/
767    
768     static void
769     usage(void)
770     {
771 ph10 287 printf("Usage: pcretest [options] [<input file> [<output file>]]\n\n");
772     printf("Input and output default to stdin and stdout.\n");
773     #ifdef SUPPORT_LIBREADLINE
774     printf("If input is a terminal, readline() is used to read from it.\n");
775     #else
776     printf("This version of pcretest is not linked with readline().\n");
777     #endif
778     printf("\nOptions:\n");
779 nigel 93 printf(" -b show compiled code (bytecode)\n");
780     printf(" -C show PCRE compile-time options and exit\n");
781     printf(" -d debug: show compiled code and information (-b and -i)\n");
782     #if !defined NODFA
783     printf(" -dfa force DFA matching for all subjects\n");
784     #endif
785     printf(" -help show usage information\n");
786     printf(" -i show information about compiled patterns\n"
787     " -m output memory used information\n"
788     " -o <n> set size of offsets vector to <n>\n");
789     #if !defined NOPOSIX
790     printf(" -p use POSIX interface\n");
791     #endif
792     printf(" -q quiet: do not output PCRE version number at start\n");
793     printf(" -S <n> set stack size to <n> megabytes\n");
794     printf(" -s output store (memory) used information\n"
795     " -t time compilation and execution\n");
796     printf(" -t <n> time compilation and execution, repeating <n> times\n");
797     printf(" -tm time execution (matching) only\n");
798     printf(" -tm <n> time execution (matching) only, repeating <n> times\n");
799     }
800    
801    
802    
803     /*************************************************
804 nigel 63 * Main Program *
805     *************************************************/
806 nigel 43
807 nigel 3 /* Read lines from named file or stdin and write to named file or stdout; lines
808     consist of a regular expression, in delimiters and optionally followed by
809     options, followed by a set of test data, terminated by an empty line. */
810    
811     int main(int argc, char **argv)
812     {
813     FILE *infile = stdin;
814     int options = 0;
815     int study_options = 0;
816     int op = 1;
817     int timeit = 0;
818 nigel 93 int timeitm = 0;
819 nigel 3 int showinfo = 0;
820 nigel 31 int showstore = 0;
821 nigel 87 int quiet = 0;
822 nigel 53 int size_offsets = 45;
823     int size_offsets_max;
824 nigel 77 int *offsets = NULL;
825 nigel 53 #if !defined NOPOSIX
826 nigel 3 int posix = 0;
827 nigel 53 #endif
828 nigel 3 int debug = 0;
829 nigel 11 int done = 0;
830 nigel 77 int all_use_dfa = 0;
831     int yield = 0;
832 nigel 91 int stack_size;
833 nigel 3
834 nigel 91 /* These vectors store, end-to-end, a list of captured substring names. Assume
835     that 1024 is plenty long enough for the few names we'll be testing. */
836 nigel 69
837 nigel 91 uschar copynames[1024];
838     uschar getnames[1024];
839    
840     uschar *copynamesptr;
841     uschar *getnamesptr;
842    
843 nigel 69 /* Get buffers from malloc() so that Electric Fence will check their misuse
844 nigel 91 when I am debugging. They grow automatically when very long lines are read. */
845 nigel 69
846 nigel 91 buffer = (unsigned char *)malloc(buffer_size);
847     dbuffer = (unsigned char *)malloc(buffer_size);
848     pbuffer = (unsigned char *)malloc(buffer_size);
849 nigel 69
850 nigel 93 /* The outfile variable is static so that new_malloc can use it. */
851 nigel 3
852 nigel 93 outfile = stdout;
853    
854     /* The following _setmode() stuff is some Windows magic that tells its runtime
855     library to translate CRLF into a single LF character. At least, that's what
856     I've been told: never having used Windows I take this all on trust. Originally
857     it set 0x8000, but then I was advised that _O_BINARY was better. */
858    
859 nigel 75 #if defined(_WIN32) || defined(WIN32)
860 nigel 93 _setmode( _fileno( stdout ), _O_BINARY );
861     #endif
862 nigel 75
863 nigel 3 /* Scan options */
864    
865     while (argc > 1 && argv[op][0] == '-')
866     {
867 nigel 63 unsigned char *endptr;
868 nigel 53
869 nigel 31 if (strcmp(argv[op], "-s") == 0 || strcmp(argv[op], "-m") == 0)
870     showstore = 1;
871 nigel 87 else if (strcmp(argv[op], "-q") == 0) quiet = 1;
872 nigel 93 else if (strcmp(argv[op], "-b") == 0) debug = 1;
873 nigel 3 else if (strcmp(argv[op], "-i") == 0) showinfo = 1;
874     else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1;
875 nigel 79 #if !defined NODFA
876 nigel 77 else if (strcmp(argv[op], "-dfa") == 0) all_use_dfa = 1;
877 nigel 79 #endif
878 nigel 53 else if (strcmp(argv[op], "-o") == 0 && argc > 2 &&
879 nigel 65 ((size_offsets = get_value((unsigned char *)argv[op+1], &endptr)),
880     *endptr == 0))
881 nigel 53 {
882     op++;
883     argc--;
884     }
885 nigel 93 else if (strcmp(argv[op], "-t") == 0 || strcmp(argv[op], "-tm") == 0)
886     {
887     int both = argv[op][2] == 0;
888     int temp;
889     if (argc > 2 && (temp = get_value((unsigned char *)argv[op+1], &endptr),
890     *endptr == 0))
891     {
892     timeitm = temp;
893     op++;
894     argc--;
895     }
896     else timeitm = LOOPREPEAT;
897     if (both) timeit = timeitm;
898     }
899 nigel 91 else if (strcmp(argv[op], "-S") == 0 && argc > 2 &&
900     ((stack_size = get_value((unsigned char *)argv[op+1], &endptr)),
901     *endptr == 0))
902     {
903 nigel 93 #if defined(_WIN32) || defined(WIN32)
904 nigel 91 printf("PCRE: -S not supported on this OS\n");
905     exit(1);
906     #else
907     int rc;
908     struct rlimit rlim;
909     getrlimit(RLIMIT_STACK, &rlim);
910     rlim.rlim_cur = stack_size * 1024 * 1024;
911     rc = setrlimit(RLIMIT_STACK, &rlim);
912     if (rc != 0)
913     {
914     printf("PCRE: setrlimit() failed with error %d\n", rc);
915     exit(1);
916     }
917     op++;
918     argc--;
919     #endif
920     }
921 nigel 53 #if !defined NOPOSIX
922 nigel 3 else if (strcmp(argv[op], "-p") == 0) posix = 1;
923 nigel 53 #endif
924 nigel 63 else if (strcmp(argv[op], "-C") == 0)
925     {
926     int rc;
927     printf("PCRE version %s\n", pcre_version());
928     printf("Compiled with\n");
929     (void)pcre_config(PCRE_CONFIG_UTF8, &rc);
930     printf(" %sUTF-8 support\n", rc? "" : "No ");
931 nigel 75 (void)pcre_config(PCRE_CONFIG_UNICODE_PROPERTIES, &rc);
932     printf(" %sUnicode properties support\n", rc? "" : "No ");
933 nigel 63 (void)pcre_config(PCRE_CONFIG_NEWLINE, &rc);
934 nigel 91 printf(" Newline sequence is %s\n", (rc == '\r')? "CR" :
935 nigel 93 (rc == '\n')? "LF" : (rc == ('\r'<<8 | '\n'))? "CRLF" :
936 ph10 150 (rc == -2)? "ANYCRLF" :
937 nigel 93 (rc == -1)? "ANY" : "???");
938 ph10 231 (void)pcre_config(PCRE_CONFIG_BSR, &rc);
939     printf(" \\R matches %s\n", rc? "CR, LF, or CRLF only" :
940     "all Unicode newlines");
941 nigel 63 (void)pcre_config(PCRE_CONFIG_LINK_SIZE, &rc);
942     printf(" Internal link size = %d\n", rc);
943     (void)pcre_config(PCRE_CONFIG_POSIX_MALLOC_THRESHOLD, &rc);
944     printf(" POSIX malloc threshold = %d\n", rc);
945     (void)pcre_config(PCRE_CONFIG_MATCH_LIMIT, &rc);
946     printf(" Default match limit = %d\n", rc);
947 nigel 87 (void)pcre_config(PCRE_CONFIG_MATCH_LIMIT_RECURSION, &rc);
948     printf(" Default recursion depth limit = %d\n", rc);
949 nigel 73 (void)pcre_config(PCRE_CONFIG_STACKRECURSE, &rc);
950     printf(" Match recursion uses %s\n", rc? "stack" : "heap");
951 ph10 121 goto EXIT;
952 nigel 63 }
953 nigel 93 else if (strcmp(argv[op], "-help") == 0 ||
954     strcmp(argv[op], "--help") == 0)
955     {
956     usage();
957     goto EXIT;
958     }
959 nigel 3 else
960     {
961 nigel 53 printf("** Unknown or malformed option %s\n", argv[op]);
962 nigel 93 usage();
963 nigel 77 yield = 1;
964     goto EXIT;
965 nigel 3 }
966     op++;
967     argc--;
968     }
969    
970 nigel 53 /* Get the store for the offsets vector, and remember what it was */
971    
972     size_offsets_max = size_offsets;
973 nigel 71 offsets = (int *)malloc(size_offsets_max * sizeof(int));
974 nigel 53 if (offsets == NULL)
975     {
976     printf("** Failed to get %d bytes of memory for offsets vector\n",
977 ph10 151 (int)(size_offsets_max * sizeof(int)));
978 nigel 77 yield = 1;
979     goto EXIT;
980 nigel 53 }
981    
982 nigel 3 /* Sort out the input and output files */
983    
984     if (argc > 1)
985     {
986 nigel 93 infile = fopen(argv[op], INPUT_MODE);
987 nigel 3 if (infile == NULL)
988     {
989     printf("** Failed to open %s\n", argv[op]);
990 nigel 77 yield = 1;
991     goto EXIT;
992 nigel 3 }
993     }
994    
995     if (argc > 2)
996     {
997 nigel 93 outfile = fopen(argv[op+1], OUTPUT_MODE);
998 nigel 3 if (outfile == NULL)
999     {
1000     printf("** Failed to open %s\n", argv[op+1]);
1001 nigel 77 yield = 1;
1002     goto EXIT;
1003 nigel 3 }
1004     }
1005    
1006     /* Set alternative malloc function */
1007    
1008     pcre_malloc = new_malloc;
1009 nigel 73 pcre_free = new_free;
1010     pcre_stack_malloc = stack_malloc;
1011     pcre_stack_free = stack_free;
1012 nigel 3
1013 nigel 87 /* Heading line unless quiet, then prompt for first regex if stdin */
1014 nigel 3
1015 nigel 87 if (!quiet) fprintf(outfile, "PCRE version %s\n\n", pcre_version());
1016 nigel 3
1017     /* Main loop */
1018    
1019 nigel 11 while (!done)
1020 nigel 3 {
1021     pcre *re = NULL;
1022     pcre_extra *extra = NULL;
1023 nigel 37
1024     #if !defined NOPOSIX /* There are still compilers that require no indent */
1025 nigel 3 regex_t preg;
1026 nigel 45 int do_posix = 0;
1027 nigel 37 #endif
1028    
1029 nigel 7 const char *error;
1030 nigel 25 unsigned char *p, *pp, *ppp;
1031 nigel 75 unsigned char *to_file = NULL;
1032 nigel 53 const unsigned char *tables = NULL;
1033 nigel 75 unsigned long int true_size, true_study_size = 0;
1034     size_t size, regex_gotten_store;
1035 nigel 3 int do_study = 0;
1036 nigel 25 int do_debug = debug;
1037 nigel 35 int do_G = 0;
1038     int do_g = 0;
1039 nigel 25 int do_showinfo = showinfo;
1040 nigel 35 int do_showrest = 0;
1041 nigel 75 int do_flip = 0;
1042 nigel 93 int erroroffset, len, delimiter, poffset;
1043 nigel 3
1044 nigel 67 use_utf8 = 0;
1045 ph10 211 debug_lengths = 1;
1046 nigel 63
1047 ph10 287 if (extend_inputline(infile, buffer, " re> ") == NULL) break;
1048 nigel 23 if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
1049 nigel 63 fflush(outfile);
1050 nigel 3
1051     p = buffer;
1052     while (isspace(*p)) p++;
1053     if (*p == 0) continue;
1054    
1055 nigel 75 /* See if the pattern is to be loaded pre-compiled from a file. */
1056 nigel 3
1057 nigel 75 if (*p == '<' && strchr((char *)(p+1), '<') == NULL)
1058     {
1059 nigel 91 unsigned long int magic, get_options;
1060 nigel 75 uschar sbuf[8];
1061     FILE *f;
1062    
1063     p++;
1064     pp = p + (int)strlen((char *)p);
1065     while (isspace(pp[-1])) pp--;
1066     *pp = 0;
1067    
1068     f = fopen((char *)p, "rb");
1069     if (f == NULL)
1070     {
1071     fprintf(outfile, "Failed to open %s: %s\n", p, strerror(errno));
1072     continue;
1073     }
1074    
1075     if (fread(sbuf, 1, 8, f) != 8) goto FAIL_READ;
1076    
1077     true_size =
1078     (sbuf[0] << 24) | (sbuf[1] << 16) | (sbuf[2] << 8) | sbuf[3];
1079     true_study_size =
1080     (sbuf[4] << 24) | (sbuf[5] << 16) | (sbuf[6] << 8) | sbuf[7];
1081    
1082     re = (real_pcre *)new_malloc(true_size);
1083     regex_gotten_store = gotten_store;
1084    
1085     if (fread(re, 1, true_size, f) != true_size) goto FAIL_READ;
1086    
1087     magic = ((real_pcre *)re)->magic_number;
1088     if (magic != MAGIC_NUMBER)
1089     {
1090     if (byteflip(magic, sizeof(magic)) == MAGIC_NUMBER)
1091     {
1092     do_flip = 1;
1093     }
1094     else
1095     {
1096     fprintf(outfile, "Data in %s is not a compiled PCRE regex\n", p);
1097     fclose(f);
1098     continue;
1099     }
1100     }
1101    
1102     fprintf(outfile, "Compiled regex%s loaded from %s\n",
1103     do_flip? " (byte-inverted)" : "", p);
1104    
1105     /* Need to know if UTF-8 for printing data strings */
1106    
1107 nigel 91 new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options);
1108     use_utf8 = (get_options & PCRE_UTF8) != 0;
1109 nigel 75
1110     /* Now see if there is any following study data */
1111    
1112     if (true_study_size != 0)
1113     {
1114     pcre_study_data *psd;
1115    
1116     extra = (pcre_extra *)new_malloc(sizeof(pcre_extra) + true_study_size);
1117     extra->flags = PCRE_EXTRA_STUDY_DATA;
1118    
1119     psd = (pcre_study_data *)(((char *)extra) + sizeof(pcre_extra));
1120     extra->study_data = psd;
1121    
1122     if (fread(psd, 1, true_study_size, f) != true_study_size)
1123     {
1124     FAIL_READ:
1125     fprintf(outfile, "Failed to read data from %s\n", p);
1126     if (extra != NULL) new_free(extra);
1127     if (re != NULL) new_free(re);
1128     fclose(f);
1129     continue;
1130     }
1131     fprintf(outfile, "Study data loaded from %s\n", p);
1132     do_study = 1; /* To get the data output if requested */
1133     }
1134     else fprintf(outfile, "No study data\n");
1135    
1136     fclose(f);
1137     goto SHOW_INFO;
1138     }
1139    
1140     /* In-line pattern (the usual case). Get the delimiter and seek the end of
1141     the pattern; if is isn't complete, read more. */
1142    
1143 nigel 3 delimiter = *p++;
1144    
1145 nigel 29 if (isalnum(delimiter) || delimiter == '\\')
1146 nigel 3 {
1147 ph10 274 fprintf(outfile, "** Delimiter must not be alphanumeric or \\\n");
1148 nigel 3 goto SKIP_DATA;
1149     }
1150    
1151     pp = p;
1152 nigel 93 poffset = p - buffer;
1153 nigel 3
1154     for(;;)
1155     {
1156 nigel 29 while (*pp != 0)
1157     {
1158     if (*pp == '\\' && pp[1] != 0) pp++;
1159     else if (*pp == delimiter) break;
1160     pp++;
1161     }
1162 nigel 3 if (*pp != 0) break;
1163 ph10 287 if ((pp = extend_inputline(infile, pp, " > ")) == NULL)
1164 nigel 3 {
1165     fprintf(outfile, "** Unexpected EOF\n");
1166 nigel 11 done = 1;
1167     goto CONTINUE;
1168 nigel 3 }
1169 nigel 23 if (infile != stdin) fprintf(outfile, "%s", (char *)pp);
1170 nigel 3 }
1171    
1172 nigel 93 /* The buffer may have moved while being extended; reset the start of data
1173     pointer to the correct relative point in the buffer. */
1174    
1175     p = buffer + poffset;
1176    
1177 nigel 29 /* If the first character after the delimiter is backslash, make
1178     the pattern end with backslash. This is purely to provide a way
1179     of testing for the error message when a pattern ends with backslash. */
1180    
1181     if (pp[1] == '\\') *pp++ = '\\';
1182    
1183 nigel 75 /* Terminate the pattern at the delimiter, and save a copy of the pattern
1184     for callouts. */
1185 nigel 3
1186     *pp++ = 0;
1187 nigel 75 strcpy((char *)pbuffer, (char *)p);
1188 nigel 3
1189     /* Look for options after final delimiter */
1190    
1191     options = 0;
1192     study_options = 0;
1193 nigel 31 log_store = showstore; /* default from command line */
1194    
1195 nigel 3 while (*pp != 0)
1196     {
1197     switch (*pp++)
1198     {
1199 nigel 77 case 'f': options |= PCRE_FIRSTLINE; break;
1200 nigel 35 case 'g': do_g = 1; break;
1201 nigel 3 case 'i': options |= PCRE_CASELESS; break;
1202     case 'm': options |= PCRE_MULTILINE; break;
1203     case 's': options |= PCRE_DOTALL; break;
1204     case 'x': options |= PCRE_EXTENDED; break;
1205 nigel 25
1206 nigel 35 case '+': do_showrest = 1; break;
1207 nigel 3 case 'A': options |= PCRE_ANCHORED; break;
1208 nigel 93 case 'B': do_debug = 1; break;
1209 nigel 75 case 'C': options |= PCRE_AUTO_CALLOUT; break;
1210 nigel 25 case 'D': do_debug = do_showinfo = 1; break;
1211 nigel 3 case 'E': options |= PCRE_DOLLAR_ENDONLY; break;
1212 nigel 75 case 'F': do_flip = 1; break;
1213 nigel 35 case 'G': do_G = 1; break;
1214 nigel 25 case 'I': do_showinfo = 1; break;
1215 nigel 91 case 'J': options |= PCRE_DUPNAMES; break;
1216 nigel 31 case 'M': log_store = 1; break;
1217 nigel 63 case 'N': options |= PCRE_NO_AUTO_CAPTURE; break;
1218 nigel 37
1219     #if !defined NOPOSIX
1220 nigel 3 case 'P': do_posix = 1; break;
1221 nigel 37 #endif
1222    
1223 nigel 3 case 'S': do_study = 1; break;
1224 nigel 19 case 'U': options |= PCRE_UNGREEDY; break;
1225 nigel 3 case 'X': options |= PCRE_EXTRA; break;
1226 ph10 126 case 'Z': debug_lengths = 0; break;
1227 nigel 67 case '8': options |= PCRE_UTF8; use_utf8 = 1; break;
1228 nigel 71 case '?': options |= PCRE_NO_UTF8_CHECK; break;
1229 nigel 25
1230     case 'L':
1231     ppp = pp;
1232 nigel 93 /* The '\r' test here is so that it works on Windows. */
1233     /* The '0' test is just in case this is an unterminated line. */
1234     while (*ppp != 0 && *ppp != '\n' && *ppp != '\r' && *ppp != ' ') ppp++;
1235 nigel 25 *ppp = 0;
1236     if (setlocale(LC_CTYPE, (const char *)pp) == NULL)
1237     {
1238     fprintf(outfile, "** Failed to set locale \"%s\"\n", pp);
1239     goto SKIP_DATA;
1240     }
1241 nigel 93 locale_set = 1;
1242 nigel 25 tables = pcre_maketables();
1243     pp = ppp;
1244     break;
1245    
1246 nigel 75 case '>':
1247     to_file = pp;
1248     while (*pp != 0) pp++;
1249     while (isspace(pp[-1])) pp--;
1250     *pp = 0;
1251     break;
1252    
1253 nigel 91 case '<':
1254     {
1255 ph10 336 if (strncmp((char *)pp, "JS>", 3) == 0)
1256     {
1257     options |= PCRE_JAVASCRIPT_COMPAT;
1258     pp += 3;
1259     }
1260     else
1261     {
1262     int x = check_newline(pp, outfile);
1263     if (x == 0) goto SKIP_DATA;
1264     options |= x;
1265     while (*pp++ != '>');
1266     }
1267 nigel 91 }
1268     break;
1269    
1270 nigel 77 case '\r': /* So that it works in Windows */
1271     case '\n':
1272     case ' ':
1273     break;
1274 nigel 75
1275 nigel 3 default:
1276     fprintf(outfile, "** Unknown option '%c'\n", pp[-1]);
1277     goto SKIP_DATA;
1278     }
1279     }
1280    
1281 nigel 11 /* Handle compiling via the POSIX interface, which doesn't support the
1282 nigel 25 timing, showing, or debugging options, nor the ability to pass over
1283     local character tables. */
1284 nigel 3
1285 nigel 37 #if !defined NOPOSIX
1286 nigel 3 if (posix || do_posix)
1287     {
1288     int rc;
1289     int cflags = 0;
1290 nigel 75
1291 nigel 3 if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE;
1292     if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE;
1293 nigel 77 if ((options & PCRE_DOTALL) != 0) cflags |= REG_DOTALL;
1294 nigel 87 if ((options & PCRE_NO_AUTO_CAPTURE) != 0) cflags |= REG_NOSUB;
1295     if ((options & PCRE_UTF8) != 0) cflags |= REG_UTF8;
1296    
1297 nigel 3 rc = regcomp(&preg, (char *)p, cflags);
1298    
1299     /* Compilation failed; go back for another re, skipping to blank line
1300     if non-interactive. */
1301    
1302     if (rc != 0)
1303     {
1304 nigel 91 (void)regerror(rc, &preg, (char *)buffer, buffer_size);
1305 nigel 3 fprintf(outfile, "Failed: POSIX code %d: %s\n", rc, buffer);
1306     goto SKIP_DATA;
1307     }
1308     }
1309    
1310     /* Handle compiling via the native interface */
1311    
1312     else
1313 nigel 37 #endif /* !defined NOPOSIX */
1314    
1315 nigel 3 {
1316 nigel 93 if (timeit > 0)
1317 nigel 3 {
1318     register int i;
1319     clock_t time_taken;
1320     clock_t start_time = clock();
1321 nigel 93 for (i = 0; i < timeit; i++)
1322 nigel 3 {
1323 nigel 25 re = pcre_compile((char *)p, options, &error, &erroroffset, tables);
1324 nigel 3 if (re != NULL) free(re);
1325     }
1326     time_taken = clock() - start_time;
1327 nigel 93 fprintf(outfile, "Compile time %.4f milliseconds\n",
1328     (((double)time_taken * 1000.0) / (double)timeit) /
1329 nigel 63 (double)CLOCKS_PER_SEC);
1330 nigel 3 }
1331    
1332 nigel 25 re = pcre_compile((char *)p, options, &error, &erroroffset, tables);
1333 nigel 3
1334     /* Compilation failed; go back for another re, skipping to blank line
1335     if non-interactive. */
1336    
1337     if (re == NULL)
1338     {
1339     fprintf(outfile, "Failed: %s at offset %d\n", error, erroroffset);
1340     SKIP_DATA:
1341     if (infile != stdin)
1342     {
1343     for (;;)
1344     {
1345 ph10 287 if (extend_inputline(infile, buffer, NULL) == NULL)
1346 nigel 11 {
1347     done = 1;
1348     goto CONTINUE;
1349     }
1350 nigel 3 len = (int)strlen((char *)buffer);
1351     while (len > 0 && isspace(buffer[len-1])) len--;
1352     if (len == 0) break;
1353     }
1354     fprintf(outfile, "\n");
1355     }
1356 nigel 25 goto CONTINUE;
1357 nigel 3 }
1358    
1359 nigel 43 /* Compilation succeeded; print data if required. There are now two
1360     info-returning functions. The old one has a limited interface and
1361     returns only limited data. Check that it agrees with the newer one. */
1362 nigel 3
1363 nigel 63 if (log_store)
1364     fprintf(outfile, "Memory allocation (code space): %d\n",
1365     (int)(gotten_store -
1366     sizeof(real_pcre) -
1367     ((real_pcre *)re)->name_count * ((real_pcre *)re)->name_entry_size));
1368    
1369 nigel 75 /* Extract the size for possible writing before possibly flipping it,
1370     and remember the store that was got. */
1371    
1372     true_size = ((real_pcre *)re)->size;
1373     regex_gotten_store = gotten_store;
1374    
1375     /* If /S was present, study the regexp to generate additional info to
1376     help with the matching. */
1377    
1378     if (do_study)
1379     {
1380 nigel 93 if (timeit > 0)
1381 nigel 75 {
1382     register int i;
1383     clock_t time_taken;
1384     clock_t start_time = clock();
1385 nigel 93 for (i = 0; i < timeit; i++)
1386 nigel 75 extra = pcre_study(re, study_options, &error);
1387     time_taken = clock() - start_time;
1388     if (extra != NULL) free(extra);
1389 nigel 93 fprintf(outfile, " Study time %.4f milliseconds\n",
1390     (((double)time_taken * 1000.0) / (double)timeit) /
1391 nigel 75 (double)CLOCKS_PER_SEC);
1392     }
1393     extra = pcre_study(re, study_options, &error);
1394     if (error != NULL)
1395     fprintf(outfile, "Failed to study: %s\n", error);
1396     else if (extra != NULL)
1397     true_study_size = ((pcre_study_data *)(extra->study_data))->size;
1398     }
1399    
1400     /* If the 'F' option was present, we flip the bytes of all the integer
1401     fields in the regex data block and the study block. This is to make it
1402     possible to test PCRE's handling of byte-flipped patterns, e.g. those
1403     compiled on a different architecture. */
1404    
1405     if (do_flip)
1406     {
1407     real_pcre *rre = (real_pcre *)re;
1408 ph10 259 rre->magic_number =
1409 ph10 255 byteflip(rre->magic_number, sizeof(rre->magic_number));
1410 nigel 75 rre->size = byteflip(rre->size, sizeof(rre->size));
1411     rre->options = byteflip(rre->options, sizeof(rre->options));
1412 ph10 255 rre->flags = (pcre_uint16)byteflip(rre->flags, sizeof(rre->flags));
1413 ph10 259 rre->top_bracket =
1414 ph10 255 (pcre_uint16)byteflip(rre->top_bracket, sizeof(rre->top_bracket));
1415 ph10 259 rre->top_backref =
1416 ph10 255 (pcre_uint16)byteflip(rre->top_backref, sizeof(rre->top_backref));
1417 ph10 259 rre->first_byte =
1418 ph10 255 (pcre_uint16)byteflip(rre->first_byte, sizeof(rre->first_byte));
1419 ph10 259 rre->req_byte =
1420 ph10 255 (pcre_uint16)byteflip(rre->req_byte, sizeof(rre->req_byte));
1421     rre->name_table_offset = (pcre_uint16)byteflip(rre->name_table_offset,
1422 nigel 75 sizeof(rre->name_table_offset));
1423 ph10 255 rre->name_entry_size = (pcre_uint16)byteflip(rre->name_entry_size,
1424 nigel 75 sizeof(rre->name_entry_size));
1425 ph10 259 rre->name_count = (pcre_uint16)byteflip(rre->name_count,
1426 ph10 255 sizeof(rre->name_count));
1427 nigel 75
1428     if (extra != NULL)
1429     {
1430     pcre_study_data *rsd = (pcre_study_data *)(extra->study_data);
1431     rsd->size = byteflip(rsd->size, sizeof(rsd->size));
1432     rsd->options = byteflip(rsd->options, sizeof(rsd->options));
1433     }
1434     }
1435    
1436     /* Extract information from the compiled data if required */
1437    
1438     SHOW_INFO:
1439    
1440 nigel 93 if (do_debug)
1441     {
1442     fprintf(outfile, "------------------------------------------------------------------\n");
1443 ph10 116 pcre_printint(re, outfile, debug_lengths);
1444 nigel 93 }
1445    
1446 nigel 25 if (do_showinfo)
1447 nigel 3 {
1448 nigel 75 unsigned long int get_options, all_options;
1449 nigel 79 #if !defined NOINFOCHECK
1450 nigel 43 int old_first_char, old_options, old_count;
1451 nigel 79 #endif
1452 ph10 226 int count, backrefmax, first_char, need_char, okpartial, jchanged,
1453 ph10 227 hascrorlf;
1454 nigel 63 int nameentrysize, namecount;
1455     const uschar *nametable;
1456 nigel 3
1457 nigel 53 new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options);
1458 nigel 43 new_info(re, NULL, PCRE_INFO_SIZE, &size);
1459     new_info(re, NULL, PCRE_INFO_CAPTURECOUNT, &count);
1460     new_info(re, NULL, PCRE_INFO_BACKREFMAX, &backrefmax);
1461 nigel 63 new_info(re, NULL, PCRE_INFO_FIRSTBYTE, &first_char);
1462 nigel 43 new_info(re, NULL, PCRE_INFO_LASTLITERAL, &need_char);
1463 nigel 63 new_info(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &nameentrysize);
1464     new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount);
1465 nigel 67 new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable);
1466 ph10 172 new_info(re, NULL, PCRE_INFO_OKPARTIAL, &okpartial);
1467     new_info(re, NULL, PCRE_INFO_JCHANGED, &jchanged);
1468 ph10 226 new_info(re, NULL, PCRE_INFO_HASCRORLF, &hascrorlf);
1469 nigel 43
1470 nigel 79 #if !defined NOINFOCHECK
1471 nigel 43 old_count = pcre_info(re, &old_options, &old_first_char);
1472 nigel 3 if (count < 0) fprintf(outfile,
1473 nigel 43 "Error %d from pcre_info()\n", count);
1474 nigel 3 else
1475     {
1476 nigel 43 if (old_count != count) fprintf(outfile,
1477     "Count disagreement: pcre_fullinfo=%d pcre_info=%d\n", count,
1478     old_count);
1479 nigel 37
1480 nigel 43 if (old_first_char != first_char) fprintf(outfile,
1481     "First char disagreement: pcre_fullinfo=%d pcre_info=%d\n",
1482     first_char, old_first_char);
1483 nigel 37
1484 nigel 53 if (old_options != (int)get_options) fprintf(outfile,
1485     "Options disagreement: pcre_fullinfo=%ld pcre_info=%d\n",
1486     get_options, old_options);
1487 nigel 43 }
1488 nigel 79 #endif
1489 nigel 43
1490 nigel 75 if (size != regex_gotten_store) fprintf(outfile,
1491 nigel 43 "Size disagreement: pcre_fullinfo=%d call to malloc for %d\n",
1492 nigel 77 (int)size, (int)regex_gotten_store);
1493 nigel 43
1494     fprintf(outfile, "Capturing subpattern count = %d\n", count);
1495     if (backrefmax > 0)
1496     fprintf(outfile, "Max back reference = %d\n", backrefmax);
1497 nigel 63
1498     if (namecount > 0)
1499     {
1500     fprintf(outfile, "Named capturing subpatterns:\n");
1501     while (namecount-- > 0)
1502     {
1503     fprintf(outfile, " %s %*s%3d\n", nametable + 2,
1504     nameentrysize - 3 - (int)strlen((char *)nametable + 2), "",
1505     GET2(nametable, 0));
1506     nametable += nameentrysize;
1507     }
1508     }
1509 ph10 172
1510 ph10 169 if (!okpartial) fprintf(outfile, "Partial matching not supported\n");
1511 ph10 227 if (hascrorlf) fprintf(outfile, "Contains explicit CR or LF match\n");
1512 nigel 63
1513 nigel 75 all_options = ((real_pcre *)re)->options;
1514 ph10 169 if (do_flip) all_options = byteflip(all_options, sizeof(all_options));
1515 nigel 75
1516 nigel 53 if (get_options == 0) fprintf(outfile, "No options\n");
1517 ph10 231 else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
1518 nigel 53 ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "",
1519     ((get_options & PCRE_CASELESS) != 0)? " caseless" : "",
1520     ((get_options & PCRE_EXTENDED) != 0)? " extended" : "",
1521     ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "",
1522 nigel 77 ((get_options & PCRE_FIRSTLINE) != 0)? " firstline" : "",
1523 nigel 53 ((get_options & PCRE_DOTALL) != 0)? " dotall" : "",
1524 ph10 231 ((get_options & PCRE_BSR_ANYCRLF) != 0)? " bsr_anycrlf" : "",
1525     ((get_options & PCRE_BSR_UNICODE) != 0)? " bsr_unicode" : "",
1526 nigel 53 ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",
1527     ((get_options & PCRE_EXTRA) != 0)? " extra" : "",
1528     ((get_options & PCRE_UNGREEDY) != 0)? " ungreedy" : "",
1529 nigel 87 ((get_options & PCRE_NO_AUTO_CAPTURE) != 0)? " no_auto_capture" : "",
1530 nigel 71 ((get_options & PCRE_UTF8) != 0)? " utf8" : "",
1531 nigel 91 ((get_options & PCRE_NO_UTF8_CHECK) != 0)? " no_utf8_check" : "",
1532     ((get_options & PCRE_DUPNAMES) != 0)? " dupnames" : "");
1533 ph10 172
1534 ph10 169 if (jchanged) fprintf(outfile, "Duplicate name status changes\n");
1535 nigel 43
1536 nigel 93 switch (get_options & PCRE_NEWLINE_BITS)
1537 nigel 91 {
1538     case PCRE_NEWLINE_CR:
1539     fprintf(outfile, "Forced newline sequence: CR\n");
1540     break;
1541 nigel 43
1542 nigel 91 case PCRE_NEWLINE_LF:
1543     fprintf(outfile, "Forced newline sequence: LF\n");
1544     break;
1545    
1546     case PCRE_NEWLINE_CRLF:
1547     fprintf(outfile, "Forced newline sequence: CRLF\n");
1548     break;
1549    
1550 ph10 149 case PCRE_NEWLINE_ANYCRLF:
1551     fprintf(outfile, "Forced newline sequence: ANYCRLF\n");
1552     break;
1553    
1554 nigel 93 case PCRE_NEWLINE_ANY:
1555     fprintf(outfile, "Forced newline sequence: ANY\n");
1556     break;
1557    
1558 nigel 91 default:
1559     break;
1560     }
1561    
1562 nigel 43 if (first_char == -1)
1563     {
1564 nigel 91 fprintf(outfile, "First char at start or follows newline\n");
1565 nigel 43 }
1566     else if (first_char < 0)
1567     {
1568     fprintf(outfile, "No first char\n");
1569     }
1570     else
1571     {
1572 nigel 63 int ch = first_char & 255;
1573 nigel 67 const char *caseless = ((first_char & REQ_CASELESS) == 0)?
1574 nigel 63 "" : " (caseless)";
1575 nigel 93 if (PRINTHEX(ch))
1576 nigel 63 fprintf(outfile, "First char = \'%c\'%s\n", ch, caseless);
1577 nigel 3 else
1578 nigel 63 fprintf(outfile, "First char = %d%s\n", ch, caseless);
1579 nigel 43 }
1580 nigel 37
1581 nigel 43 if (need_char < 0)
1582     {
1583     fprintf(outfile, "No need char\n");
1584 nigel 3 }
1585 nigel 43 else
1586     {
1587 nigel 63 int ch = need_char & 255;
1588 nigel 67 const char *caseless = ((need_char & REQ_CASELESS) == 0)?
1589 nigel 63 "" : " (caseless)";
1590 nigel 93 if (PRINTHEX(ch))
1591 nigel 63 fprintf(outfile, "Need char = \'%c\'%s\n", ch, caseless);
1592 nigel 43 else
1593 nigel 63 fprintf(outfile, "Need char = %d%s\n", ch, caseless);
1594 nigel 43 }
1595 nigel 75
1596     /* Don't output study size; at present it is in any case a fixed
1597     value, but it varies, depending on the computer architecture, and
1598     so messes up the test suite. (And with the /F option, it might be
1599     flipped.) */
1600    
1601     if (do_study)
1602     {
1603     if (extra == NULL)
1604     fprintf(outfile, "Study returned NULL\n");
1605     else
1606     {
1607     uschar *start_bits = NULL;
1608     new_info(re, extra, PCRE_INFO_FIRSTTABLE, &start_bits);
1609    
1610     if (start_bits == NULL)
1611     fprintf(outfile, "No starting byte set\n");
1612     else
1613     {
1614     int i;
1615     int c = 24;
1616     fprintf(outfile, "Starting byte set: ");
1617     for (i = 0; i < 256; i++)
1618     {
1619     if ((start_bits[i/8] & (1<<(i&7))) != 0)
1620     {
1621     if (c > 75)
1622     {
1623     fprintf(outfile, "\n ");
1624     c = 2;
1625     }
1626 nigel 93 if (PRINTHEX(i) && i != ' ')
1627 nigel 75 {
1628     fprintf(outfile, "%c ", i);
1629     c += 2;
1630     }
1631     else
1632     {
1633     fprintf(outfile, "\\x%02x ", i);
1634     c += 5;
1635     }
1636     }
1637     }
1638     fprintf(outfile, "\n");
1639     }
1640     }
1641     }
1642 nigel 3 }
1643    
1644 nigel 75 /* If the '>' option was present, we write out the regex to a file, and
1645     that is all. The first 8 bytes of the file are the regex length and then
1646     the study length, in big-endian order. */
1647 nigel 3
1648 nigel 75 if (to_file != NULL)
1649 nigel 3 {
1650 nigel 75 FILE *f = fopen((char *)to_file, "wb");
1651     if (f == NULL)
1652 nigel 3 {
1653 nigel 75 fprintf(outfile, "Unable to open %s: %s\n", to_file, strerror(errno));
1654 nigel 3 }
1655 nigel 75 else
1656     {
1657     uschar sbuf[8];
1658 ph10 255 sbuf[0] = (uschar)((true_size >> 24) & 255);
1659     sbuf[1] = (uschar)((true_size >> 16) & 255);
1660     sbuf[2] = (uschar)((true_size >> 8) & 255);
1661     sbuf[3] = (uschar)((true_size) & 255);
1662 ph10 259
1663 ph10 255 sbuf[4] = (uschar)((true_study_size >> 24) & 255);
1664     sbuf[5] = (uschar)((true_study_size >> 16) & 255);
1665     sbuf[6] = (uschar)((true_study_size >> 8) & 255);
1666     sbuf[7] = (uschar)((true_study_size) & 255);
1667 nigel 3
1668 nigel 75 if (fwrite(sbuf, 1, 8, f) < 8 ||
1669     fwrite(re, 1, true_size, f) < true_size)
1670     {
1671     fprintf(outfile, "Write error on %s: %s\n", to_file, strerror(errno));
1672     }
1673 nigel 3 else
1674     {
1675 nigel 75 fprintf(outfile, "Compiled regex written to %s\n", to_file);
1676     if (extra != NULL)
1677 nigel 3 {
1678 nigel 75 if (fwrite(extra->study_data, 1, true_study_size, f) <
1679     true_study_size)
1680 nigel 3 {
1681 nigel 75 fprintf(outfile, "Write error on %s: %s\n", to_file,
1682     strerror(errno));
1683 nigel 3 }
1684 nigel 75 else fprintf(outfile, "Study data written to %s\n", to_file);
1685 nigel 93
1686 nigel 3 }
1687     }
1688 nigel 75 fclose(f);
1689 nigel 3 }
1690 nigel 77
1691     new_free(re);
1692     if (extra != NULL) new_free(extra);
1693     if (tables != NULL) new_free((void *)tables);
1694 nigel 75 continue; /* With next regex */
1695 nigel 3 }
1696 nigel 75 } /* End of non-POSIX compile */
1697 nigel 3
1698     /* Read data lines and test them */
1699    
1700     for (;;)
1701     {
1702 nigel 87 uschar *q;
1703 ph10 147 uschar *bptr;
1704 nigel 57 int *use_offsets = offsets;
1705 nigel 53 int use_size_offsets = size_offsets;
1706 nigel 63 int callout_data = 0;
1707     int callout_data_set = 0;
1708 nigel 3 int count, c;
1709 nigel 29 int copystrings = 0;
1710 nigel 63 int find_match_limit = 0;
1711 nigel 29 int getstrings = 0;
1712     int getlist = 0;
1713 nigel 39 int gmatched = 0;
1714 nigel 35 int start_offset = 0;
1715 nigel 41 int g_notempty = 0;
1716 nigel 77 int use_dfa = 0;
1717 nigel 3
1718     options = 0;
1719    
1720 nigel 91 *copynames = 0;
1721     *getnames = 0;
1722    
1723     copynamesptr = copynames;
1724     getnamesptr = getnames;
1725    
1726 nigel 63 pcre_callout = callout;
1727     first_callout = 1;
1728     callout_extra = 0;
1729     callout_count = 0;
1730     callout_fail_count = 999999;
1731     callout_fail_id = -1;
1732 nigel 73 show_malloc = 0;
1733 nigel 63
1734 nigel 91 if (extra != NULL) extra->flags &=
1735     ~(PCRE_EXTRA_MATCH_LIMIT|PCRE_EXTRA_MATCH_LIMIT_RECURSION);
1736    
1737     len = 0;
1738     for (;;)
1739 nigel 11 {
1740 ph10 287 if (extend_inputline(infile, buffer + len, "data> ") == NULL)
1741 nigel 91 {
1742     if (len > 0) break;
1743     done = 1;
1744     goto CONTINUE;
1745     }
1746     if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
1747     len = (int)strlen((char *)buffer);
1748     if (buffer[len-1] == '\n') break;
1749 nigel 11 }
1750 nigel 3
1751     while (len > 0 && isspace(buffer[len-1])) len--;
1752     buffer[len] = 0;
1753     if (len == 0) break;
1754    
1755     p = buffer;
1756     while (isspace(*p)) p++;
1757    
1758 ph10 147 bptr = q = dbuffer;
1759 nigel 3 while ((c = *p++) != 0)
1760     {
1761     int i = 0;
1762     int n = 0;
1763 nigel 63
1764 nigel 3 if (c == '\\') switch ((c = *p++))
1765     {
1766     case 'a': c = 7; break;
1767     case 'b': c = '\b'; break;
1768     case 'e': c = 27; break;
1769     case 'f': c = '\f'; break;
1770     case 'n': c = '\n'; break;
1771     case 'r': c = '\r'; break;
1772     case 't': c = '\t'; break;
1773     case 'v': c = '\v'; break;
1774    
1775     case '0': case '1': case '2': case '3':
1776     case '4': case '5': case '6': case '7':
1777     c -= '0';
1778     while (i++ < 2 && isdigit(*p) && *p != '8' && *p != '9')
1779     c = c * 8 + *p++ - '0';
1780 nigel 91
1781     #if !defined NOUTF8
1782     if (use_utf8 && c > 255)
1783     {
1784     unsigned char buff8[8];
1785     int ii, utn;
1786     utn = ord2utf8(c, buff8);
1787     for (ii = 0; ii < utn - 1; ii++) *q++ = buff8[ii];
1788     c = buff8[ii]; /* Last byte */
1789     }
1790     #endif
1791 nigel 3 break;
1792    
1793     case 'x':
1794 nigel 49
1795     /* Handle \x{..} specially - new Perl thing for utf8 */
1796    
1797 nigel 79 #if !defined NOUTF8
1798 nigel 49 if (*p == '{')
1799     {
1800     unsigned char *pt = p;
1801     c = 0;
1802     while (isxdigit(*(++pt)))
1803     c = c * 16 + tolower(*pt) - ((isdigit(*pt))? '0' : 'W');
1804     if (*pt == '}')
1805     {
1806 nigel 67 unsigned char buff8[8];
1807 nigel 49 int ii, utn;
1808 nigel 85 utn = ord2utf8(c, buff8);
1809 nigel 67 for (ii = 0; ii < utn - 1; ii++) *q++ = buff8[ii];
1810     c = buff8[ii]; /* Last byte */
1811 nigel 49 p = pt + 1;
1812     break;
1813     }
1814     /* Not correct form; fall through */
1815     }
1816 nigel 79 #endif
1817 nigel 49
1818     /* Ordinary \x */
1819    
1820 nigel 3 c = 0;
1821     while (i++ < 2 && isxdigit(*p))
1822     {
1823     c = c * 16 + tolower(*p) - ((isdigit(*p))? '0' : 'W');
1824     p++;
1825     }
1826     break;
1827    
1828 nigel 75 case 0: /* \ followed by EOF allows for an empty line */
1829 nigel 3 p--;
1830     continue;
1831    
1832 nigel 75 case '>':
1833     while(isdigit(*p)) start_offset = start_offset * 10 + *p++ - '0';
1834     continue;
1835    
1836 nigel 3 case 'A': /* Option setting */
1837     options |= PCRE_ANCHORED;
1838     continue;
1839    
1840     case 'B':
1841     options |= PCRE_NOTBOL;
1842     continue;
1843    
1844 nigel 29 case 'C':
1845 nigel 63 if (isdigit(*p)) /* Set copy string */
1846     {
1847     while(isdigit(*p)) n = n * 10 + *p++ - '0';
1848     copystrings |= 1 << n;
1849     }
1850     else if (isalnum(*p))
1851     {
1852 nigel 91 uschar *npp = copynamesptr;
1853 nigel 67 while (isalnum(*p)) *npp++ = *p++;
1854 nigel 91 *npp++ = 0;
1855 nigel 67 *npp = 0;
1856 nigel 91 n = pcre_get_stringnumber(re, (char *)copynamesptr);
1857 nigel 63 if (n < 0)
1858 nigel 91 fprintf(outfile, "no parentheses with name \"%s\"\n", copynamesptr);
1859     copynamesptr = npp;
1860 nigel 63 }
1861     else if (*p == '+')
1862     {
1863     callout_extra = 1;
1864     p++;
1865     }
1866     else if (*p == '-')
1867     {
1868     pcre_callout = NULL;
1869     p++;
1870     }
1871     else if (*p == '!')
1872     {
1873     callout_fail_id = 0;
1874     p++;
1875     while(isdigit(*p))
1876     callout_fail_id = callout_fail_id * 10 + *p++ - '0';
1877     callout_fail_count = 0;
1878     if (*p == '!')
1879     {
1880     p++;
1881     while(isdigit(*p))
1882     callout_fail_count = callout_fail_count * 10 + *p++ - '0';
1883     }
1884     }
1885     else if (*p == '*')
1886     {
1887     int sign = 1;
1888     callout_data = 0;
1889     if (*(++p) == '-') { sign = -1; p++; }
1890     while(isdigit(*p))
1891     callout_data = callout_data * 10 + *p++ - '0';
1892     callout_data *= sign;
1893     callout_data_set = 1;
1894     }
1895 nigel 29 continue;
1896    
1897 nigel 79 #if !defined NODFA
1898 nigel 77 case 'D':
1899 nigel 79 #if !defined NOPOSIX
1900 nigel 77 if (posix || do_posix)
1901     printf("** Can't use dfa matching in POSIX mode: \\D ignored\n");
1902     else
1903 nigel 79 #endif
1904 nigel 77 use_dfa = 1;
1905     continue;
1906    
1907     case 'F':
1908     options |= PCRE_DFA_SHORTEST;
1909     continue;
1910 nigel 79 #endif
1911 nigel 77
1912 nigel 29 case 'G':
1913 nigel 63 if (isdigit(*p))
1914     {
1915     while(isdigit(*p)) n = n * 10 + *p++ - '0';
1916     getstrings |= 1 << n;
1917     }
1918     else if (isalnum(*p))
1919     {
1920 nigel 91 uschar *npp = getnamesptr;
1921 nigel 67 while (isalnum(*p)) *npp++ = *p++;
1922 nigel 91 *npp++ = 0;
1923 nigel 67 *npp = 0;
1924 nigel 91 n = pcre_get_stringnumber(re, (char *)getnamesptr);
1925 nigel 63 if (n < 0)
1926 nigel 91 fprintf(outfile, "no parentheses with name \"%s\"\n", getnamesptr);
1927     getnamesptr = npp;
1928 nigel 63 }
1929 nigel 29 continue;
1930    
1931     case 'L':
1932     getlist = 1;
1933     continue;
1934    
1935 nigel 63 case 'M':
1936     find_match_limit = 1;
1937     continue;
1938    
1939 nigel 37 case 'N':
1940     options |= PCRE_NOTEMPTY;
1941     continue;
1942    
1943 nigel 3 case 'O':
1944     while(isdigit(*p)) n = n * 10 + *p++ - '0';
1945 nigel 53 if (n > size_offsets_max)
1946     {
1947     size_offsets_max = n;
1948 nigel 57 free(offsets);
1949 nigel 71 use_offsets = offsets = (int *)malloc(size_offsets_max * sizeof(int));
1950 nigel 53 if (offsets == NULL)
1951     {
1952     printf("** Failed to get %d bytes of memory for offsets vector\n",
1953 ph10 151 (int)(size_offsets_max * sizeof(int)));
1954 nigel 77 yield = 1;
1955     goto EXIT;
1956 nigel 53 }
1957     }
1958     use_size_offsets = n;
1959 nigel 63 if (n == 0) use_offsets = NULL; /* Ensures it can't write to it */
1960 nigel 3 continue;
1961    
1962 nigel 75 case 'P':
1963     options |= PCRE_PARTIAL;
1964     continue;
1965    
1966 nigel 91 case 'Q':
1967     while(isdigit(*p)) n = n * 10 + *p++ - '0';
1968     if (extra == NULL)
1969     {
1970     extra = (pcre_extra *)malloc(sizeof(pcre_extra));
1971     extra->flags = 0;
1972     }
1973     extra->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
1974     extra->match_limit_recursion = n;
1975     continue;
1976    
1977     case 'q':
1978     while(isdigit(*p)) n = n * 10 + *p++ - '0';
1979     if (extra == NULL)
1980     {
1981     extra = (pcre_extra *)malloc(sizeof(pcre_extra));
1982     extra->flags = 0;
1983     }
1984     extra->flags |= PCRE_EXTRA_MATCH_LIMIT;
1985     extra->match_limit = n;
1986     continue;
1987    
1988 nigel 79 #if !defined NODFA
1989 nigel 77 case 'R':
1990     options |= PCRE_DFA_RESTART;
1991     continue;
1992 nigel 79 #endif
1993 nigel 77
1994 nigel 73 case 'S':
1995     show_malloc = 1;
1996     continue;
1997    
1998 nigel 3 case 'Z':
1999     options |= PCRE_NOTEOL;
2000     continue;
2001 nigel 71
2002     case '?':
2003     options |= PCRE_NO_UTF8_CHECK;
2004     continue;
2005 nigel 91
2006     case '<':
2007     {
2008     int x = check_newline(p, outfile);
2009     if (x == 0) goto NEXT_DATA;
2010     options |= x;
2011     while (*p++ != '>');
2012     }
2013     continue;
2014 nigel 3 }
2015 nigel 9 *q++ = c;
2016 nigel 3 }
2017 nigel 9 *q = 0;
2018     len = q - dbuffer;
2019 nigel 3
2020 nigel 77 if ((all_use_dfa || use_dfa) && find_match_limit)
2021     {
2022     printf("**Match limit not relevant for DFA matching: ignored\n");
2023     find_match_limit = 0;
2024     }
2025    
2026 nigel 3 /* Handle matching via the POSIX interface, which does not
2027 nigel 63 support timing or playing with the match limit or callout data. */
2028 nigel 3
2029 nigel 37 #if !defined NOPOSIX
2030 nigel 3 if (posix || do_posix)
2031     {
2032     int rc;
2033     int eflags = 0;
2034 nigel 63 regmatch_t *pmatch = NULL;
2035     if (use_size_offsets > 0)
2036 nigel 71 pmatch = (regmatch_t *)malloc(sizeof(regmatch_t) * use_size_offsets);
2037 nigel 3 if ((options & PCRE_NOTBOL) != 0) eflags |= REG_NOTBOL;
2038     if ((options & PCRE_NOTEOL) != 0) eflags |= REG_NOTEOL;
2039    
2040 nigel 53 rc = regexec(&preg, (const char *)bptr, use_size_offsets, pmatch, eflags);
2041 nigel 3
2042     if (rc != 0)
2043     {
2044 nigel 91 (void)regerror(rc, &preg, (char *)buffer, buffer_size);
2045 nigel 3 fprintf(outfile, "No match: POSIX code %d: %s\n", rc, buffer);
2046     }
2047 nigel 87 else if ((((const pcre *)preg.re_pcre)->options & PCRE_NO_AUTO_CAPTURE)
2048     != 0)
2049     {
2050     fprintf(outfile, "Matched with REG_NOSUB\n");
2051     }
2052 nigel 3 else
2053     {
2054 nigel 7 size_t i;
2055 nigel 63 for (i = 0; i < (size_t)use_size_offsets; i++)
2056 nigel 3 {
2057     if (pmatch[i].rm_so >= 0)
2058     {
2059 nigel 23 fprintf(outfile, "%2d: ", (int)i);
2060 nigel 63 (void)pchars(dbuffer + pmatch[i].rm_so,
2061     pmatch[i].rm_eo - pmatch[i].rm_so, outfile);
2062 nigel 3 fprintf(outfile, "\n");
2063 nigel 35 if (i == 0 && do_showrest)
2064     {
2065     fprintf(outfile, " 0+ ");
2066 nigel 63 (void)pchars(dbuffer + pmatch[i].rm_eo, len - pmatch[i].rm_eo,
2067     outfile);
2068 nigel 35 fprintf(outfile, "\n");
2069     }
2070 nigel 3 }
2071     }
2072     }
2073 nigel 53 free(pmatch);
2074 nigel 3 }
2075    
2076 nigel 35 /* Handle matching via the native interface - repeats for /g and /G */
2077 nigel 3
2078 nigel 37 else
2079     #endif /* !defined NOPOSIX */
2080    
2081 nigel 39 for (;; gmatched++) /* Loop for /g or /G */
2082 nigel 3 {
2083 nigel 93 if (timeitm > 0)
2084 nigel 3 {
2085     register int i;
2086     clock_t time_taken;
2087     clock_t start_time = clock();
2088 nigel 77
2089 nigel 79 #if !defined NODFA
2090 nigel 77 if (all_use_dfa || use_dfa)
2091     {
2092     int workspace[1000];
2093 nigel 93 for (i = 0; i < timeitm; i++)
2094 nigel 77 count = pcre_dfa_exec(re, NULL, (char *)bptr, len, start_offset,
2095     options | g_notempty, use_offsets, use_size_offsets, workspace,
2096     sizeof(workspace)/sizeof(int));
2097     }
2098     else
2099 nigel 79 #endif
2100 nigel 77
2101 nigel 93 for (i = 0; i < timeitm; i++)
2102 nigel 35 count = pcre_exec(re, extra, (char *)bptr, len,
2103 nigel 57 start_offset, options | g_notempty, use_offsets, use_size_offsets);
2104 nigel 77
2105 nigel 3 time_taken = clock() - start_time;
2106 nigel 93 fprintf(outfile, "Execute time %.4f milliseconds\n",
2107     (((double)time_taken * 1000.0) / (double)timeitm) /
2108 nigel 63 (double)CLOCKS_PER_SEC);
2109 nigel 3 }
2110    
2111 nigel 63 /* If find_match_limit is set, we want to do repeated matches with
2112 nigel 87 varying limits in order to find the minimum value for the match limit and
2113     for the recursion limit. */
2114 nigel 63
2115     if (find_match_limit)
2116     {
2117     if (extra == NULL)
2118     {
2119 nigel 71 extra = (pcre_extra *)malloc(sizeof(pcre_extra));
2120 nigel 63 extra->flags = 0;
2121     }
2122    
2123 nigel 91 (void)check_match_limit(re, extra, bptr, len, start_offset,
2124 nigel 87 options|g_notempty, use_offsets, use_size_offsets,
2125     PCRE_EXTRA_MATCH_LIMIT, &(extra->match_limit),
2126     PCRE_ERROR_MATCHLIMIT, "match()");
2127 nigel 63
2128 nigel 87 count = check_match_limit(re, extra, bptr, len, start_offset,
2129     options|g_notempty, use_offsets, use_size_offsets,
2130     PCRE_EXTRA_MATCH_LIMIT_RECURSION, &(extra->match_limit_recursion),
2131     PCRE_ERROR_RECURSIONLIMIT, "match() recursion");
2132 nigel 63 }
2133    
2134     /* If callout_data is set, use the interface with additional data */
2135    
2136     else if (callout_data_set)
2137     {
2138     if (extra == NULL)
2139     {
2140 nigel 71 extra = (pcre_extra *)malloc(sizeof(pcre_extra));
2141 nigel 63 extra->flags = 0;
2142     }
2143     extra->flags |= PCRE_EXTRA_CALLOUT_DATA;
2144 nigel 71 extra->callout_data = &callout_data;
2145 nigel 63 count = pcre_exec(re, extra, (char *)bptr, len, start_offset,
2146     options | g_notempty, use_offsets, use_size_offsets);
2147     extra->flags &= ~PCRE_EXTRA_CALLOUT_DATA;
2148     }
2149    
2150     /* The normal case is just to do the match once, with the default
2151     value of match_limit. */
2152    
2153 nigel 79 #if !defined NODFA
2154 nigel 77 else if (all_use_dfa || use_dfa)
2155     {
2156     int workspace[1000];
2157     count = pcre_dfa_exec(re, NULL, (char *)bptr, len, start_offset,
2158     options | g_notempty, use_offsets, use_size_offsets, workspace,
2159     sizeof(workspace)/sizeof(int));
2160     if (count == 0)
2161     {
2162     fprintf(outfile, "Matched, but too many subsidiary matches\n");
2163     count = use_size_offsets/2;
2164     }
2165     }
2166 nigel 79 #endif
2167 nigel 77
2168 nigel 75 else
2169     {
2170     count = pcre_exec(re, extra, (char *)bptr, len,
2171     start_offset, options | g_notempty, use_offsets, use_size_offsets);
2172 nigel 77 if (count == 0)
2173     {
2174     fprintf(outfile, "Matched, but too many substrings\n");
2175     count = use_size_offsets/3;
2176     }
2177 nigel 75 }
2178 nigel 3
2179 nigel 39 /* Matched */
2180    
2181 nigel 3 if (count >= 0)
2182     {
2183 nigel 93 int i, maxcount;
2184    
2185     #if !defined NODFA
2186     if (all_use_dfa || use_dfa) maxcount = use_size_offsets/2; else
2187     #endif
2188     maxcount = use_size_offsets/3;
2189    
2190     /* This is a check against a lunatic return value. */
2191    
2192     if (count > maxcount)
2193     {
2194     fprintf(outfile,
2195     "** PCRE error: returned count %d is too big for offset size %d\n",
2196     count, use_size_offsets);
2197     count = use_size_offsets/3;
2198     if (do_g || do_G)
2199     {
2200     fprintf(outfile, "** /%c loop abandoned\n", do_g? 'g' : 'G');
2201     do_g = do_G = FALSE; /* Break g/G loop */
2202     }
2203     }
2204    
2205 nigel 29 for (i = 0; i < count * 2; i += 2)
2206 nigel 3 {
2207 nigel 57 if (use_offsets[i] < 0)
2208 nigel 3 fprintf(outfile, "%2d: <unset>\n", i/2);
2209     else
2210     {
2211     fprintf(outfile, "%2d: ", i/2);
2212 nigel 63 (void)pchars(bptr + use_offsets[i],
2213     use_offsets[i+1] - use_offsets[i], outfile);
2214 nigel 3 fprintf(outfile, "\n");
2215 nigel 35 if (i == 0)
2216     {
2217     if (do_showrest)
2218     {
2219     fprintf(outfile, " 0+ ");
2220 nigel 63 (void)pchars(bptr + use_offsets[i+1], len - use_offsets[i+1],
2221     outfile);
2222 nigel 35 fprintf(outfile, "\n");
2223     }
2224     }
2225 nigel 3 }
2226     }
2227 nigel 29
2228     for (i = 0; i < 32; i++)
2229     {
2230     if ((copystrings & (1 << i)) != 0)
2231     {
2232 nigel 91 char copybuffer[256];
2233 nigel 57 int rc = pcre_copy_substring((char *)bptr, use_offsets, count,
2234 nigel 37 i, copybuffer, sizeof(copybuffer));
2235 nigel 29 if (rc < 0)
2236     fprintf(outfile, "copy substring %d failed %d\n", i, rc);
2237     else
2238 nigel 37 fprintf(outfile, "%2dC %s (%d)\n", i, copybuffer, rc);
2239 nigel 29 }
2240     }
2241    
2242 nigel 91 for (copynamesptr = copynames;
2243     *copynamesptr != 0;
2244     copynamesptr += (int)strlen((char*)copynamesptr) + 1)
2245     {
2246     char copybuffer[256];
2247     int rc = pcre_copy_named_substring(re, (char *)bptr, use_offsets,
2248     count, (char *)copynamesptr, copybuffer, sizeof(copybuffer));
2249     if (rc < 0)
2250     fprintf(outfile, "copy substring %s failed %d\n", copynamesptr, rc);
2251     else
2252     fprintf(outfile, " C %s (%d) %s\n", copybuffer, rc, copynamesptr);
2253     }
2254    
2255 nigel 29 for (i = 0; i < 32; i++)
2256     {
2257     if ((getstrings & (1 << i)) != 0)
2258     {
2259     const char *substring;
2260 nigel 57 int rc = pcre_get_substring((char *)bptr, use_offsets, count,
2261 nigel 29 i, &substring);
2262     if (rc < 0)
2263     fprintf(outfile, "get substring %d failed %d\n", i, rc);
2264     else
2265     {
2266     fprintf(outfile, "%2dG %s (%d)\n", i, substring, rc);
2267 nigel 49 pcre_free_substring(substring);
2268 nigel 29 }
2269     }
2270     }
2271    
2272 nigel 91 for (getnamesptr = getnames;
2273     *getnamesptr != 0;
2274     getnamesptr += (int)strlen((char*)getnamesptr) + 1)
2275     {
2276     const char *substring;
2277     int rc = pcre_get_named_substring(re, (char *)bptr, use_offsets,
2278     count, (char *)getnamesptr, &substring);
2279     if (rc < 0)
2280     fprintf(outfile, "copy substring %s failed %d\n", getnamesptr, rc);
2281     else
2282     {
2283     fprintf(outfile, " G %s (%d) %s\n", substring, rc, getnamesptr);
2284     pcre_free_substring(substring);
2285     }
2286     }
2287    
2288 nigel 29 if (getlist)
2289     {
2290     const char **stringlist;
2291 nigel 57 int rc = pcre_get_substring_list((char *)bptr, use_offsets, count,
2292 nigel 29 &stringlist);
2293     if (rc < 0)
2294     fprintf(outfile, "get substring list failed %d\n", rc);
2295     else
2296     {
2297     for (i = 0; i < count; i++)
2298     fprintf(outfile, "%2dL %s\n", i, stringlist[i]);
2299     if (stringlist[i] != NULL)
2300     fprintf(outfile, "string list not terminated by NULL\n");
2301 nigel 49 /* free((void *)stringlist); */
2302     pcre_free_substring_list(stringlist);
2303 nigel 29 }
2304     }
2305 nigel 39 }
2306 nigel 29
2307 nigel 75 /* There was a partial match */
2308    
2309     else if (count == PCRE_ERROR_PARTIAL)
2310     {
2311 nigel 77 fprintf(outfile, "Partial match");
2312 nigel 79 #if !defined NODFA
2313 nigel 77 if ((all_use_dfa || use_dfa) && use_size_offsets > 2)
2314     fprintf(outfile, ": %.*s", use_offsets[1] - use_offsets[0],
2315     bptr + use_offsets[0]);
2316 nigel 79 #endif
2317 nigel 77 fprintf(outfile, "\n");
2318 nigel 75 break; /* Out of the /g loop */
2319     }
2320    
2321 nigel 41 /* Failed to match. If this is a /g or /G loop and we previously set
2322 ph10 143 g_notempty after a null match, this is not necessarily the end. We want
2323     to advance the start offset, and continue. We won't be at the end of the
2324     string - that was checked before setting g_notempty.
2325 nigel 39
2326 ph10 150 Complication arises in the case when the newline option is "any" or
2327 ph10 149 "anycrlf". If the previous match was at the end of a line terminated by
2328     CRLF, an advance of one character just passes the \r, whereas we should
2329     prefer the longer newline sequence, as does the code in pcre_exec().
2330     Fudge the offset value to achieve this.
2331 ph10 144
2332 ph10 143 Otherwise, in the case of UTF-8 matching, the advance must be one
2333     character, not one byte. */
2334    
2335 nigel 3 else
2336     {
2337 nigel 41 if (g_notempty != 0)
2338 nigel 35 {
2339 nigel 73 int onechar = 1;
2340 ph10 146 unsigned int obits = ((real_pcre *)re)->options;
2341 nigel 57 use_offsets[0] = start_offset;
2342 ph10 146 if ((obits & PCRE_NEWLINE_BITS) == 0)
2343     {
2344     int d;
2345     (void)pcre_config(PCRE_CONFIG_NEWLINE, &d);
2346     obits = (d == '\r')? PCRE_NEWLINE_CR :
2347     (d == '\n')? PCRE_NEWLINE_LF :
2348     (d == ('\r'<<8 | '\n'))? PCRE_NEWLINE_CRLF :
2349 ph10 150 (d == -2)? PCRE_NEWLINE_ANYCRLF :
2350 ph10 146 (d == -1)? PCRE_NEWLINE_ANY : 0;
2351     }
2352 ph10 149 if (((obits & PCRE_NEWLINE_BITS) == PCRE_NEWLINE_ANY ||
2353 ph10 150 (obits & PCRE_NEWLINE_BITS) == PCRE_NEWLINE_ANYCRLF)
2354 ph10 149 &&
2355 ph10 143 start_offset < len - 1 &&
2356     bptr[start_offset] == '\r' &&
2357     bptr[start_offset+1] == '\n')
2358 ph10 144 onechar++;
2359 ph10 143 else if (use_utf8)
2360 nigel 73 {
2361     while (start_offset + onechar < len)
2362     {
2363     int tb = bptr[start_offset+onechar];
2364     if (tb <= 127) break;
2365     tb &= 0xc0;
2366     if (tb != 0 && tb != 0xc0) onechar++;
2367     }
2368     }
2369     use_offsets[1] = start_offset + onechar;
2370 nigel 35 }
2371 nigel 41 else
2372     {
2373 nigel 73 if (count == PCRE_ERROR_NOMATCH)
2374 nigel 41 {
2375 nigel 73 if (gmatched == 0) fprintf(outfile, "No match\n");
2376 nigel 41 }
2377 nigel 73 else fprintf(outfile, "Error %d\n", count);
2378 nigel 41 break; /* Out of the /g loop */
2379     }
2380 nigel 3 }
2381 nigel 35
2382 nigel 39 /* If not /g or /G we are done */
2383    
2384     if (!do_g && !do_G) break;
2385    
2386 nigel 41 /* If we have matched an empty string, first check to see if we are at
2387     the end of the subject. If so, the /g loop is over. Otherwise, mimic
2388     what Perl's /g options does. This turns out to be rather cunning. First
2389 nigel 47 we set PCRE_NOTEMPTY and PCRE_ANCHORED and try the match again at the
2390     same point. If this fails (picked up above) we advance to the next
2391 ph10 143 character. */
2392 ph10 142
2393 nigel 41 g_notempty = 0;
2394 ph10 142
2395 nigel 57 if (use_offsets[0] == use_offsets[1])
2396 nigel 41 {
2397 nigel 57 if (use_offsets[0] == len) break;
2398 nigel 47 g_notempty = PCRE_NOTEMPTY | PCRE_ANCHORED;
2399 nigel 41 }
2400 nigel 39
2401     /* For /g, update the start offset, leaving the rest alone */
2402    
2403 ph10 143 if (do_g) start_offset = use_offsets[1];
2404 nigel 39
2405     /* For /G, update the pointer and length */
2406    
2407     else
2408 nigel 35 {
2409 ph10 143 bptr += use_offsets[1];
2410     len -= use_offsets[1];
2411 nigel 35 }
2412 nigel 39 } /* End of loop for /g and /G */
2413 nigel 91
2414     NEXT_DATA: continue;
2415 nigel 39 } /* End of loop for data lines */
2416 nigel 3
2417 nigel 11 CONTINUE:
2418 nigel 37
2419     #if !defined NOPOSIX
2420 nigel 3 if (posix || do_posix) regfree(&preg);
2421 nigel 37 #endif
2422    
2423 nigel 77 if (re != NULL) new_free(re);
2424     if (extra != NULL) new_free(extra);
2425 nigel 25 if (tables != NULL)
2426     {
2427 nigel 77 new_free((void *)tables);
2428 nigel 25 setlocale(LC_CTYPE, "C");
2429 nigel 93 locale_set = 0;
2430 nigel 25 }
2431 nigel 3 }
2432    
2433 nigel 73 if (infile == stdin) fprintf(outfile, "\n");
2434 nigel 77
2435     EXIT:
2436    
2437     if (infile != NULL && infile != stdin) fclose(infile);
2438     if (outfile != NULL && outfile != stdout) fclose(outfile);
2439    
2440     free(buffer);
2441     free(dbuffer);
2442     free(pbuffer);
2443     free(offsets);
2444    
2445     return yield;
2446 nigel 3 }
2447    
2448 nigel 77 /* End of pcretest.c */

Properties

Name Value
svn:eol-style native
svn:keywords "Author Date Id Revision Url"

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12