4 |
|
|
5 |
/* This program was hacked up as a tester for PCRE. I really should have |
/* 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 |
written it more tidily in the first place. Will I ever learn? It has grown and |
7 |
been extended and consequently is now rather untidy in places. |
been extended and consequently is now rather, er, *very* untidy in places. |
8 |
|
|
9 |
----------------------------------------------------------------------------- |
----------------------------------------------------------------------------- |
10 |
Redistribution and use in source and binary forms, with or without |
Redistribution and use in source and binary forms, with or without |
44 |
#include <locale.h> |
#include <locale.h> |
45 |
#include <errno.h> |
#include <errno.h> |
46 |
|
|
|
/* We need the internal info for displaying the results of pcre_study(). Also |
|
|
for getting the opcodes for showing compiled code. */ |
|
|
|
|
47 |
#define PCRE_SPY /* For Win32 build, import data, not export */ |
#define PCRE_SPY /* For Win32 build, import data, not export */ |
48 |
#include "internal.h" |
|
49 |
|
/* We include pcre_internal.h because we need the internal info for displaying |
50 |
|
the results of pcre_study() and we also need to know about the internal |
51 |
|
macros, structures, and other internal data values; pcretest has "inside |
52 |
|
information" compared to a program that strictly follows the PCRE API. */ |
53 |
|
|
54 |
|
#include "pcre_internal.h" |
55 |
|
|
56 |
|
/* We need access to the data tables that PCRE uses. So as not to have to keep |
57 |
|
two copies, we include the source file here, changing the names of the external |
58 |
|
symbols to prevent clashes. */ |
59 |
|
|
60 |
|
#define _pcre_utf8_table1 utf8_table1 |
61 |
|
#define _pcre_utf8_table1_size utf8_table1_size |
62 |
|
#define _pcre_utf8_table2 utf8_table2 |
63 |
|
#define _pcre_utf8_table3 utf8_table3 |
64 |
|
#define _pcre_utf8_table4 utf8_table4 |
65 |
|
#define _pcre_utt utt |
66 |
|
#define _pcre_utt_size utt_size |
67 |
|
#define _pcre_OP_lengths OP_lengths |
68 |
|
|
69 |
|
#include "pcre_tables.c" |
70 |
|
|
71 |
|
/* We also need the pcre_printint() function for printing out compiled |
72 |
|
patterns. This function is in a separate file so that it can be included in |
73 |
|
pcre_compile.c when that module is compiled with debugging enabled. */ |
74 |
|
|
75 |
|
#include "pcre_printint.src" |
76 |
|
|
77 |
|
|
78 |
/* It is possible to compile this test program without including support for |
/* It is possible to compile this test program without including support for |
79 |
testing the POSIX interface, though this is not available via the standard |
testing the POSIX interface, though this is not available via the standard |
83 |
#include "pcreposix.h" |
#include "pcreposix.h" |
84 |
#endif |
#endif |
85 |
|
|
86 |
|
/* It is also possible, for the benefit of the version imported into Exim, to |
87 |
|
build pcretest without support for UTF8 (define NOUTF8), without the interface |
88 |
|
to the DFA matcher (NODFA), and without the doublecheck of the old "info" |
89 |
|
function (define NOINFOCHECK). */ |
90 |
|
|
91 |
|
|
92 |
|
/* Other parameters */ |
93 |
|
|
94 |
#ifndef CLOCKS_PER_SEC |
#ifndef CLOCKS_PER_SEC |
95 |
#ifdef CLK_TCK |
#ifdef CLK_TCK |
96 |
#define CLOCKS_PER_SEC CLK_TCK |
#define CLOCKS_PER_SEC CLK_TCK |
106 |
#define DBUFFER_SIZE BUFFER_SIZE |
#define DBUFFER_SIZE BUFFER_SIZE |
107 |
|
|
108 |
|
|
109 |
|
/* Static variables */ |
110 |
|
|
111 |
static FILE *outfile; |
static FILE *outfile; |
112 |
static int log_store = 0; |
static int log_store = 0; |
113 |
static int callout_count; |
static int callout_count; |
122 |
static uschar *pbuffer = NULL; |
static uschar *pbuffer = NULL; |
123 |
|
|
124 |
|
|
|
static const int utf8_table1[] = { |
|
|
0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff}; |
|
|
|
|
|
static const int utf8_table2[] = { |
|
|
0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; |
|
|
|
|
|
static const int utf8_table3[] = { |
|
|
0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; |
|
|
|
|
|
|
|
|
|
|
|
/************************************************* |
|
|
* Print compiled regex * |
|
|
*************************************************/ |
|
|
|
|
|
/* The code for doing this is held in a separate file that is also included in |
|
|
pcre.c when it is compiled with the debug switch. It defines a function called |
|
|
print_internals(), which uses a table of opcode lengths defined by the macro |
|
|
OP_LENGTHS, whose name must be OP_lengths. It also uses a table that translates |
|
|
Unicode property names to numbers; this is kept in a separate file. */ |
|
|
|
|
|
static uschar OP_lengths[] = { OP_LENGTHS }; |
|
|
|
|
|
#include "ucp.h" |
|
|
#include "ucptypetable.c" |
|
|
#include "printint.c" |
|
|
|
|
|
|
|
125 |
|
|
126 |
/************************************************* |
/************************************************* |
127 |
* Read number from string * |
* Read number from string * |
150 |
|
|
151 |
|
|
152 |
|
|
|
/************************************************* |
|
|
* Convert character value to UTF-8 * |
|
|
*************************************************/ |
|
|
|
|
|
/* This function takes an integer value in the range 0 - 0x7fffffff |
|
|
and encodes it as a UTF-8 character in 0 to 6 bytes. |
|
|
|
|
|
Arguments: |
|
|
cvalue the character value |
|
|
buffer pointer to buffer for result - at least 6 bytes long |
|
|
|
|
|
Returns: number of characters placed in the buffer |
|
|
-1 if input character is negative |
|
|
0 if input character is positive but too big (only when |
|
|
int is longer than 32 bits) |
|
|
*/ |
|
|
|
|
|
static int |
|
|
ord2utf8(int cvalue, unsigned char *buffer) |
|
|
{ |
|
|
register int i, j; |
|
|
for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) |
|
|
if (cvalue <= utf8_table1[i]) break; |
|
|
if (i >= sizeof(utf8_table1)/sizeof(int)) return 0; |
|
|
if (cvalue < 0) return -1; |
|
|
|
|
|
buffer += i; |
|
|
for (j = i; j > 0; j--) |
|
|
{ |
|
|
*buffer-- = 0x80 | (cvalue & 0x3f); |
|
|
cvalue >>= 6; |
|
|
} |
|
|
*buffer = utf8_table2[i] | cvalue; |
|
|
return i + 1; |
|
|
} |
|
|
|
|
153 |
|
|
154 |
/************************************************* |
/************************************************* |
155 |
* Convert UTF-8 string to value * |
* Convert UTF-8 string to value * |
166 |
-6 to 0 => malformed UTF-8 character at offset = (-return) |
-6 to 0 => malformed UTF-8 character at offset = (-return) |
167 |
*/ |
*/ |
168 |
|
|
169 |
|
#if !defined NOUTF8 |
170 |
|
|
171 |
static int |
static int |
172 |
utf82ord(unsigned char *buffer, int *vptr) |
utf82ord(unsigned char *buffer, int *vptr) |
173 |
{ |
{ |
199 |
|
|
200 |
/* Check that encoding was the correct unique one */ |
/* Check that encoding was the correct unique one */ |
201 |
|
|
202 |
for (j = 0; j < sizeof(utf8_table1)/sizeof(int); j++) |
for (j = 0; j < utf8_table1_size; j++) |
203 |
if (d <= utf8_table1[j]) break; |
if (d <= utf8_table1[j]) break; |
204 |
if (j != i) return -(i+1); |
if (j != i) return -(i+1); |
205 |
|
|
209 |
return i+1; |
return i+1; |
210 |
} |
} |
211 |
|
|
212 |
|
#endif |
213 |
|
|
214 |
|
|
215 |
|
|
216 |
|
/************************************************* |
217 |
|
* Convert character value to UTF-8 * |
218 |
|
*************************************************/ |
219 |
|
|
220 |
|
/* This function takes an integer value in the range 0 - 0x7fffffff |
221 |
|
and encodes it as a UTF-8 character in 0 to 6 bytes. |
222 |
|
|
223 |
|
Arguments: |
224 |
|
cvalue the character value |
225 |
|
buffer pointer to buffer for result - at least 6 bytes long |
226 |
|
|
227 |
|
Returns: number of characters placed in the buffer |
228 |
|
*/ |
229 |
|
|
230 |
|
static int |
231 |
|
ord2utf8(int cvalue, uschar *buffer) |
232 |
|
{ |
233 |
|
register int i, j; |
234 |
|
for (i = 0; i < utf8_table1_size; i++) |
235 |
|
if (cvalue <= utf8_table1[i]) break; |
236 |
|
buffer += i; |
237 |
|
for (j = i; j > 0; j--) |
238 |
|
{ |
239 |
|
*buffer-- = 0x80 | (cvalue & 0x3f); |
240 |
|
cvalue >>= 6; |
241 |
|
} |
242 |
|
*buffer = utf8_table2[i] | cvalue; |
243 |
|
return i + 1; |
244 |
|
} |
245 |
|
|
246 |
|
|
247 |
|
|
248 |
/************************************************* |
/************************************************* |
255 |
|
|
256 |
static int pchars(unsigned char *p, int length, FILE *f) |
static int pchars(unsigned char *p, int length, FILE *f) |
257 |
{ |
{ |
258 |
int c; |
int c = 0; |
259 |
int yield = 0; |
int yield = 0; |
260 |
|
|
261 |
while (length-- > 0) |
while (length-- > 0) |
262 |
{ |
{ |
263 |
|
#if !defined NOUTF8 |
264 |
if (use_utf8) |
if (use_utf8) |
265 |
{ |
{ |
266 |
int rc = utf82ord(p, &c); |
int rc = utf82ord(p, &c); |
283 |
continue; |
continue; |
284 |
} |
} |
285 |
} |
} |
286 |
|
#endif |
287 |
|
|
288 |
/* Not UTF-8, or malformed UTF-8 */ |
/* Not UTF-8, or malformed UTF-8 */ |
289 |
|
|
412 |
void *block = malloc(size); |
void *block = malloc(size); |
413 |
gotten_store = size; |
gotten_store = size; |
414 |
if (show_malloc) |
if (show_malloc) |
415 |
fprintf(outfile, "malloc %3d %p\n", size, block); |
fprintf(outfile, "malloc %3d %p\n", (int)size, block); |
416 |
return block; |
return block; |
417 |
} |
} |
418 |
|
|
430 |
{ |
{ |
431 |
void *block = malloc(size); |
void *block = malloc(size); |
432 |
if (show_malloc) |
if (show_malloc) |
433 |
fprintf(outfile, "stack_malloc %3d %p\n", size, block); |
fprintf(outfile, "stack_malloc %3d %p\n", (int)size, block); |
434 |
return block; |
return block; |
435 |
} |
} |
436 |
|
|
493 |
int showstore = 0; |
int showstore = 0; |
494 |
int size_offsets = 45; |
int size_offsets = 45; |
495 |
int size_offsets_max; |
int size_offsets_max; |
496 |
int *offsets; |
int *offsets = NULL; |
497 |
#if !defined NOPOSIX |
#if !defined NOPOSIX |
498 |
int posix = 0; |
int posix = 0; |
499 |
#endif |
#endif |
500 |
int debug = 0; |
int debug = 0; |
501 |
int done = 0; |
int done = 0; |
502 |
|
int all_use_dfa = 0; |
503 |
|
int yield = 0; |
504 |
|
|
505 |
unsigned char *buffer; |
unsigned char *buffer; |
506 |
unsigned char *dbuffer; |
unsigned char *dbuffer; |
533 |
else if (strcmp(argv[op], "-t") == 0) timeit = 1; |
else if (strcmp(argv[op], "-t") == 0) timeit = 1; |
534 |
else if (strcmp(argv[op], "-i") == 0) showinfo = 1; |
else if (strcmp(argv[op], "-i") == 0) showinfo = 1; |
535 |
else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1; |
else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1; |
536 |
|
#if !defined NODFA |
537 |
|
else if (strcmp(argv[op], "-dfa") == 0) all_use_dfa = 1; |
538 |
|
#endif |
539 |
else if (strcmp(argv[op], "-o") == 0 && argc > 2 && |
else if (strcmp(argv[op], "-o") == 0 && argc > 2 && |
540 |
((size_offsets = get_value((unsigned char *)argv[op+1], &endptr)), |
((size_offsets = get_value((unsigned char *)argv[op+1], &endptr)), |
541 |
*endptr == 0)) |
*endptr == 0)) |
572 |
printf("** Unknown or malformed option %s\n", argv[op]); |
printf("** Unknown or malformed option %s\n", argv[op]); |
573 |
printf("Usage: pcretest [-d] [-i] [-o <n>] [-p] [-s] [-t] [<input> [<output>]]\n"); |
printf("Usage: pcretest [-d] [-i] [-o <n>] [-p] [-s] [-t] [<input> [<output>]]\n"); |
574 |
printf(" -C show PCRE compile-time options and exit\n"); |
printf(" -C show PCRE compile-time options and exit\n"); |
575 |
printf(" -d debug: show compiled code; implies -i\n" |
printf(" -d debug: show compiled code; implies -i\n"); |
576 |
" -i show information about compiled pattern\n" |
#if !defined NODFA |
577 |
|
printf(" -dfa force DFA matching for all subjects\n"); |
578 |
|
#endif |
579 |
|
printf(" -i show information about compiled pattern\n" |
580 |
" -m output memory used information\n" |
" -m output memory used information\n" |
581 |
" -o <n> set size of offsets vector to <n>\n"); |
" -o <n> set size of offsets vector to <n>\n"); |
582 |
#if !defined NOPOSIX |
#if !defined NOPOSIX |
584 |
#endif |
#endif |
585 |
printf(" -s output store (memory) used information\n" |
printf(" -s output store (memory) used information\n" |
586 |
" -t time compilation and execution\n"); |
" -t time compilation and execution\n"); |
587 |
return 1; |
yield = 1; |
588 |
|
goto EXIT; |
589 |
} |
} |
590 |
op++; |
op++; |
591 |
argc--; |
argc--; |
599 |
{ |
{ |
600 |
printf("** Failed to get %d bytes of memory for offsets vector\n", |
printf("** Failed to get %d bytes of memory for offsets vector\n", |
601 |
size_offsets_max * sizeof(int)); |
size_offsets_max * sizeof(int)); |
602 |
return 1; |
yield = 1; |
603 |
|
goto EXIT; |
604 |
} |
} |
605 |
|
|
606 |
/* Sort out the input and output files */ |
/* Sort out the input and output files */ |
611 |
if (infile == NULL) |
if (infile == NULL) |
612 |
{ |
{ |
613 |
printf("** Failed to open %s\n", argv[op]); |
printf("** Failed to open %s\n", argv[op]); |
614 |
return 1; |
yield = 1; |
615 |
|
goto EXIT; |
616 |
} |
} |
617 |
} |
} |
618 |
|
|
622 |
if (outfile == NULL) |
if (outfile == NULL) |
623 |
{ |
{ |
624 |
printf("** Failed to open %s\n", argv[op+1]); |
printf("** Failed to open %s\n", argv[op+1]); |
625 |
return 1; |
yield = 1; |
626 |
|
goto EXIT; |
627 |
} |
} |
628 |
} |
} |
629 |
|
|
823 |
{ |
{ |
824 |
switch (*pp++) |
switch (*pp++) |
825 |
{ |
{ |
826 |
|
case 'f': options |= PCRE_FIRSTLINE; break; |
827 |
case 'g': do_g = 1; break; |
case 'g': do_g = 1; break; |
828 |
case 'i': options |= PCRE_CASELESS; break; |
case 'i': options |= PCRE_CASELESS; break; |
829 |
case 'm': options |= PCRE_MULTILINE; break; |
case 'm': options |= PCRE_MULTILINE; break; |
853 |
|
|
854 |
case 'L': |
case 'L': |
855 |
ppp = pp; |
ppp = pp; |
856 |
while (*ppp != '\n' && *ppp != ' ') ppp++; |
/* The '\r' test here is so that it works on Windows */ |
857 |
|
while (*ppp != '\n' && *ppp != '\r' && *ppp != ' ') ppp++; |
858 |
*ppp = 0; |
*ppp = 0; |
859 |
if (setlocale(LC_CTYPE, (const char *)pp) == NULL) |
if (setlocale(LC_CTYPE, (const char *)pp) == NULL) |
860 |
{ |
{ |
872 |
*pp = 0; |
*pp = 0; |
873 |
break; |
break; |
874 |
|
|
875 |
case '\n': case ' ': break; |
case '\r': /* So that it works in Windows */ |
876 |
|
case '\n': |
877 |
|
case ' ': |
878 |
|
break; |
879 |
|
|
880 |
default: |
default: |
881 |
fprintf(outfile, "** Unknown option '%c'\n", pp[-1]); |
fprintf(outfile, "** Unknown option '%c'\n", pp[-1]); |
895 |
|
|
896 |
if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE; |
if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE; |
897 |
if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE; |
if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE; |
898 |
|
if ((options & PCRE_DOTALL) != 0) cflags |= REG_DOTALL; |
899 |
rc = regcomp(&preg, (char *)p, cflags); |
rc = regcomp(&preg, (char *)p, cflags); |
900 |
|
|
901 |
/* Compilation failed; go back for another re, skipping to blank line |
/* Compilation failed; go back for another re, skipping to blank line |
1035 |
if (do_showinfo) |
if (do_showinfo) |
1036 |
{ |
{ |
1037 |
unsigned long int get_options, all_options; |
unsigned long int get_options, all_options; |
1038 |
|
#if !defined NOINFOCHECK |
1039 |
int old_first_char, old_options, old_count; |
int old_first_char, old_options, old_count; |
1040 |
|
#endif |
1041 |
int count, backrefmax, first_char, need_char; |
int count, backrefmax, first_char, need_char; |
1042 |
int nameentrysize, namecount; |
int nameentrysize, namecount; |
1043 |
const uschar *nametable; |
const uschar *nametable; |
1045 |
if (do_debug) |
if (do_debug) |
1046 |
{ |
{ |
1047 |
fprintf(outfile, "------------------------------------------------------------------\n"); |
fprintf(outfile, "------------------------------------------------------------------\n"); |
1048 |
print_internals(re, outfile); |
pcre_printint(re, outfile); |
1049 |
} |
} |
1050 |
|
|
1051 |
new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options); |
new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options); |
1058 |
new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount); |
new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount); |
1059 |
new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable); |
new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable); |
1060 |
|
|
1061 |
|
#if !defined NOINFOCHECK |
1062 |
old_count = pcre_info(re, &old_options, &old_first_char); |
old_count = pcre_info(re, &old_options, &old_first_char); |
1063 |
if (count < 0) fprintf(outfile, |
if (count < 0) fprintf(outfile, |
1064 |
"Error %d from pcre_info()\n", count); |
"Error %d from pcre_info()\n", count); |
1076 |
"Options disagreement: pcre_fullinfo=%ld pcre_info=%d\n", |
"Options disagreement: pcre_fullinfo=%ld pcre_info=%d\n", |
1077 |
get_options, old_options); |
get_options, old_options); |
1078 |
} |
} |
1079 |
|
#endif |
1080 |
|
|
1081 |
if (size != regex_gotten_store) fprintf(outfile, |
if (size != regex_gotten_store) fprintf(outfile, |
1082 |
"Size disagreement: pcre_fullinfo=%d call to malloc for %d\n", |
"Size disagreement: pcre_fullinfo=%d call to malloc for %d\n", |
1083 |
size, regex_gotten_store); |
(int)size, (int)regex_gotten_store); |
1084 |
|
|
1085 |
fprintf(outfile, "Capturing subpattern count = %d\n", count); |
fprintf(outfile, "Capturing subpattern count = %d\n", count); |
1086 |
if (backrefmax > 0) |
if (backrefmax > 0) |
1111 |
fprintf(outfile, "Partial matching not supported\n"); |
fprintf(outfile, "Partial matching not supported\n"); |
1112 |
|
|
1113 |
if (get_options == 0) fprintf(outfile, "No options\n"); |
if (get_options == 0) fprintf(outfile, "No options\n"); |
1114 |
else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s%s%s\n", |
else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s%s%s%s\n", |
1115 |
((get_options & PCRE_ANCHORED) != 0)? " anchored" : "", |
((get_options & PCRE_ANCHORED) != 0)? " anchored" : "", |
1116 |
((get_options & PCRE_CASELESS) != 0)? " caseless" : "", |
((get_options & PCRE_CASELESS) != 0)? " caseless" : "", |
1117 |
((get_options & PCRE_EXTENDED) != 0)? " extended" : "", |
((get_options & PCRE_EXTENDED) != 0)? " extended" : "", |
1118 |
((get_options & PCRE_MULTILINE) != 0)? " multiline" : "", |
((get_options & PCRE_MULTILINE) != 0)? " multiline" : "", |
1119 |
|
((get_options & PCRE_FIRSTLINE) != 0)? " firstline" : "", |
1120 |
((get_options & PCRE_DOTALL) != 0)? " dotall" : "", |
((get_options & PCRE_DOTALL) != 0)? " dotall" : "", |
1121 |
((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "", |
((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "", |
1122 |
((get_options & PCRE_EXTRA) != 0)? " extra" : "", |
((get_options & PCRE_EXTRA) != 0)? " extra" : "", |
1254 |
} |
} |
1255 |
fclose(f); |
fclose(f); |
1256 |
} |
} |
1257 |
|
|
1258 |
|
new_free(re); |
1259 |
|
if (extra != NULL) new_free(extra); |
1260 |
|
if (tables != NULL) new_free((void *)tables); |
1261 |
continue; /* With next regex */ |
continue; /* With next regex */ |
1262 |
} |
} |
1263 |
} /* End of non-POSIX compile */ |
} /* End of non-POSIX compile */ |
1280 |
int gmatched = 0; |
int gmatched = 0; |
1281 |
int start_offset = 0; |
int start_offset = 0; |
1282 |
int g_notempty = 0; |
int g_notempty = 0; |
1283 |
|
int use_dfa = 0; |
1284 |
|
|
1285 |
options = 0; |
options = 0; |
1286 |
|
|
1336 |
|
|
1337 |
/* Handle \x{..} specially - new Perl thing for utf8 */ |
/* Handle \x{..} specially - new Perl thing for utf8 */ |
1338 |
|
|
1339 |
|
#if !defined NOUTF8 |
1340 |
if (*p == '{') |
if (*p == '{') |
1341 |
{ |
{ |
1342 |
unsigned char *pt = p; |
unsigned char *pt = p; |
1355 |
} |
} |
1356 |
/* Not correct form; fall through */ |
/* Not correct form; fall through */ |
1357 |
} |
} |
1358 |
|
#endif |
1359 |
|
|
1360 |
/* Ordinary \x */ |
/* Ordinary \x */ |
1361 |
|
|
1436 |
} |
} |
1437 |
continue; |
continue; |
1438 |
|
|
1439 |
|
#if !defined NODFA |
1440 |
|
case 'D': |
1441 |
|
#if !defined NOPOSIX |
1442 |
|
if (posix || do_posix) |
1443 |
|
printf("** Can't use dfa matching in POSIX mode: \\D ignored\n"); |
1444 |
|
else |
1445 |
|
#endif |
1446 |
|
use_dfa = 1; |
1447 |
|
continue; |
1448 |
|
|
1449 |
|
case 'F': |
1450 |
|
options |= PCRE_DFA_SHORTEST; |
1451 |
|
continue; |
1452 |
|
#endif |
1453 |
|
|
1454 |
case 'G': |
case 'G': |
1455 |
if (isdigit(*p)) |
if (isdigit(*p)) |
1456 |
{ |
{ |
1493 |
{ |
{ |
1494 |
printf("** Failed to get %d bytes of memory for offsets vector\n", |
printf("** Failed to get %d bytes of memory for offsets vector\n", |
1495 |
size_offsets_max * sizeof(int)); |
size_offsets_max * sizeof(int)); |
1496 |
return 1; |
yield = 1; |
1497 |
|
goto EXIT; |
1498 |
} |
} |
1499 |
} |
} |
1500 |
use_size_offsets = n; |
use_size_offsets = n; |
1505 |
options |= PCRE_PARTIAL; |
options |= PCRE_PARTIAL; |
1506 |
continue; |
continue; |
1507 |
|
|
1508 |
|
#if !defined NODFA |
1509 |
|
case 'R': |
1510 |
|
options |= PCRE_DFA_RESTART; |
1511 |
|
continue; |
1512 |
|
#endif |
1513 |
|
|
1514 |
case 'S': |
case 'S': |
1515 |
show_malloc = 1; |
show_malloc = 1; |
1516 |
continue; |
continue; |
1528 |
*q = 0; |
*q = 0; |
1529 |
len = q - dbuffer; |
len = q - dbuffer; |
1530 |
|
|
1531 |
|
if ((all_use_dfa || use_dfa) && find_match_limit) |
1532 |
|
{ |
1533 |
|
printf("**Match limit not relevant for DFA matching: ignored\n"); |
1534 |
|
find_match_limit = 0; |
1535 |
|
} |
1536 |
|
|
1537 |
/* Handle matching via the POSIX interface, which does not |
/* Handle matching via the POSIX interface, which does not |
1538 |
support timing or playing with the match limit or callout data. */ |
support timing or playing with the match limit or callout data. */ |
1539 |
|
|
1591 |
register int i; |
register int i; |
1592 |
clock_t time_taken; |
clock_t time_taken; |
1593 |
clock_t start_time = clock(); |
clock_t start_time = clock(); |
1594 |
|
|
1595 |
|
#if !defined NODFA |
1596 |
|
if (all_use_dfa || use_dfa) |
1597 |
|
{ |
1598 |
|
int workspace[1000]; |
1599 |
|
for (i = 0; i < LOOPREPEAT; i++) |
1600 |
|
count = pcre_dfa_exec(re, NULL, (char *)bptr, len, start_offset, |
1601 |
|
options | g_notempty, use_offsets, use_size_offsets, workspace, |
1602 |
|
sizeof(workspace)/sizeof(int)); |
1603 |
|
} |
1604 |
|
else |
1605 |
|
#endif |
1606 |
|
|
1607 |
for (i = 0; i < LOOPREPEAT; i++) |
for (i = 0; i < LOOPREPEAT; i++) |
1608 |
count = pcre_exec(re, extra, (char *)bptr, len, |
count = pcre_exec(re, extra, (char *)bptr, len, |
1609 |
start_offset, options | g_notempty, use_offsets, use_size_offsets); |
start_offset, options | g_notempty, use_offsets, use_size_offsets); |
1610 |
|
|
1611 |
time_taken = clock() - start_time; |
time_taken = clock() - start_time; |
1612 |
fprintf(outfile, "Execute time %.3f milliseconds\n", |
fprintf(outfile, "Execute time %.3f milliseconds\n", |
1613 |
(((double)time_taken * 1000.0) / (double)LOOPREPEAT) / |
(((double)time_taken * 1000.0) / (double)LOOPREPEAT) / |
1678 |
/* The normal case is just to do the match once, with the default |
/* The normal case is just to do the match once, with the default |
1679 |
value of match_limit. */ |
value of match_limit. */ |
1680 |
|
|
1681 |
else |
#if !defined NODFA |
1682 |
|
else if (all_use_dfa || use_dfa) |
1683 |
{ |
{ |
1684 |
count = pcre_exec(re, extra, (char *)bptr, len, |
int workspace[1000]; |
1685 |
start_offset, options | g_notempty, use_offsets, use_size_offsets); |
count = pcre_dfa_exec(re, NULL, (char *)bptr, len, start_offset, |
1686 |
|
options | g_notempty, use_offsets, use_size_offsets, workspace, |
1687 |
|
sizeof(workspace)/sizeof(int)); |
1688 |
|
if (count == 0) |
1689 |
|
{ |
1690 |
|
fprintf(outfile, "Matched, but too many subsidiary matches\n"); |
1691 |
|
count = use_size_offsets/2; |
1692 |
|
} |
1693 |
} |
} |
1694 |
|
#endif |
1695 |
|
|
1696 |
if (count == 0) |
else |
1697 |
{ |
{ |
1698 |
fprintf(outfile, "Matched, but too many substrings\n"); |
count = pcre_exec(re, extra, (char *)bptr, len, |
1699 |
count = use_size_offsets/3; |
start_offset, options | g_notempty, use_offsets, use_size_offsets); |
1700 |
|
if (count == 0) |
1701 |
|
{ |
1702 |
|
fprintf(outfile, "Matched, but too many substrings\n"); |
1703 |
|
count = use_size_offsets/3; |
1704 |
|
} |
1705 |
} |
} |
1706 |
|
|
1707 |
/* Matched */ |
/* Matched */ |
1787 |
|
|
1788 |
else if (count == PCRE_ERROR_PARTIAL) |
else if (count == PCRE_ERROR_PARTIAL) |
1789 |
{ |
{ |
1790 |
fprintf(outfile, "Partial match\n"); |
fprintf(outfile, "Partial match"); |
1791 |
|
#if !defined NODFA |
1792 |
|
if ((all_use_dfa || use_dfa) && use_size_offsets > 2) |
1793 |
|
fprintf(outfile, ": %.*s", use_offsets[1] - use_offsets[0], |
1794 |
|
bptr + use_offsets[0]); |
1795 |
|
#endif |
1796 |
|
fprintf(outfile, "\n"); |
1797 |
break; /* Out of the /g loop */ |
break; /* Out of the /g loop */ |
1798 |
} |
} |
1799 |
|
|
1871 |
if (posix || do_posix) regfree(&preg); |
if (posix || do_posix) regfree(&preg); |
1872 |
#endif |
#endif |
1873 |
|
|
1874 |
if (re != NULL) free(re); |
if (re != NULL) new_free(re); |
1875 |
if (extra != NULL) free(extra); |
if (extra != NULL) new_free(extra); |
1876 |
if (tables != NULL) |
if (tables != NULL) |
1877 |
{ |
{ |
1878 |
free((void *)tables); |
new_free((void *)tables); |
1879 |
setlocale(LC_CTYPE, "C"); |
setlocale(LC_CTYPE, "C"); |
1880 |
} |
} |
1881 |
} |
} |
1882 |
|
|
1883 |
if (infile == stdin) fprintf(outfile, "\n"); |
if (infile == stdin) fprintf(outfile, "\n"); |
1884 |
return 0; |
|
1885 |
|
EXIT: |
1886 |
|
|
1887 |
|
if (infile != NULL && infile != stdin) fclose(infile); |
1888 |
|
if (outfile != NULL && outfile != stdout) fclose(outfile); |
1889 |
|
|
1890 |
|
free(buffer); |
1891 |
|
free(dbuffer); |
1892 |
|
free(pbuffer); |
1893 |
|
free(offsets); |
1894 |
|
|
1895 |
|
return yield; |
1896 |
} |
} |
1897 |
|
|
1898 |
/* End */ |
/* End of pcretest.c */ |