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

Diff of /code/trunk/pcretest.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 75 by nigel, Sat Feb 24 21:40:37 2007 UTC revision 87 by nigel, Sat Feb 24 21:41:21 2007 UTC
# Line 4  Line 4 
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
# Line 44  POSSIBILITY OF SUCH DAMAGE. Line 44  POSSIBILITY OF SUCH DAMAGE.
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
# Line 58  Makefile. */ Line 83  Makefile. */
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
# Line 73  Makefile. */ Line 106  Makefile. */
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;
# Line 87  static size_t gotten_store; Line 122  static size_t gotten_store;
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               *
# Line 143  return(result); Line 150  return(result);
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       *
# Line 195  Returns:   >  0 => the number of bytes c Line 166  Returns:   >  0 => the number of bytes c
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  {  {
# Line 226  for (j = 0; j < i; j++) Line 199  for (j = 0; j < i; j++)
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    
# Line 236  if (j != i) return -(i+1); Line 209  if (j != i) return -(i+1);
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  /*************************************************  /*************************************************
# Line 248  chars without printing. */ Line 255  chars without printing. */
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);
# Line 275  while (length-- > 0) Line 283  while (length-- > 0)
283        continue;        continue;
284        }        }
285      }      }
286    #endif
287    
288     /* Not UTF-8, or malformed UTF-8  */     /* Not UTF-8, or malformed UTF-8  */
289    
# Line 403  static void *new_malloc(size_t size) Line 412  static void *new_malloc(size_t size)
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    
# Line 421  static void *stack_malloc(size_t size) Line 430  static void *stack_malloc(size_t size)
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    
# Line 466  return ((value & 0x000000ff) << 24) | Line 475  return ((value & 0x000000ff) << 24) |
475    
476    
477  /*************************************************  /*************************************************
478    *        Check match or recursion limit          *
479    *************************************************/
480    
481    static int
482    check_match_limit(pcre *re, pcre_extra *extra, uschar *bptr, int len,
483      int start_offset, int options, int *use_offsets, int use_size_offsets,
484      int flag, unsigned long int *limit, int errnumber, const char *msg)
485    {
486    int count;
487    int min = 0;
488    int mid = 64;
489    int max = -1;
490    
491    extra->flags |= flag;
492    
493    for (;;)
494      {
495      *limit = mid;
496    
497      count = pcre_exec(re, extra, (char *)bptr, len, start_offset, options,
498        use_offsets, use_size_offsets);
499    
500      if (count == errnumber)
501        {
502        /* fprintf(outfile, "Testing %s limit = %d\n", msg, mid); */
503        min = mid;
504        mid = (mid == max - 1)? max : (max > 0)? (min + max)/2 : mid*2;
505        }
506    
507      else if (count >= 0 || count == PCRE_ERROR_NOMATCH ||
508                             count == PCRE_ERROR_PARTIAL)
509        {
510        if (mid == min + 1)
511          {
512          fprintf(outfile, "Minimum %s limit = %d\n", msg, mid);
513          break;
514          }
515        /* fprintf(outfile, "Testing %s limit = %d\n", msg, mid); */
516        max = mid;
517        mid = (min + mid)/2;
518        }
519      else break;    /* Some other error */
520      }
521    
522    extra->flags &= ~flag;
523    return count;
524    }
525    
526    
527    
528    /*************************************************
529  *                Main Program                    *  *                Main Program                    *
530  *************************************************/  *************************************************/
531    
# Line 482  int op = 1; Line 542  int op = 1;
542  int timeit = 0;  int timeit = 0;
543  int showinfo = 0;  int showinfo = 0;
544  int showstore = 0;  int showstore = 0;
545    int quiet = 0;
546  int size_offsets = 45;  int size_offsets = 45;
547  int size_offsets_max;  int size_offsets_max;
548  int *offsets;  int *offsets = NULL;
549  #if !defined NOPOSIX  #if !defined NOPOSIX
550  int posix = 0;  int posix = 0;
551  #endif  #endif
552  int debug = 0;  int debug = 0;
553  int done = 0;  int done = 0;
554    int all_use_dfa = 0;
555    int yield = 0;
556    
557  unsigned char *buffer;  unsigned char *buffer;
558  unsigned char *dbuffer;  unsigned char *dbuffer;
# Line 520  while (argc > 1 && argv[op][0] == '-') Line 583  while (argc > 1 && argv[op][0] == '-')
583    if (strcmp(argv[op], "-s") == 0 || strcmp(argv[op], "-m") == 0)    if (strcmp(argv[op], "-s") == 0 || strcmp(argv[op], "-m") == 0)
584      showstore = 1;      showstore = 1;
585    else if (strcmp(argv[op], "-t") == 0) timeit = 1;    else if (strcmp(argv[op], "-t") == 0) timeit = 1;
586      else if (strcmp(argv[op], "-q") == 0) quiet = 1;
587    else if (strcmp(argv[op], "-i") == 0) showinfo = 1;    else if (strcmp(argv[op], "-i") == 0) showinfo = 1;
588    else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1;    else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1;
589    #if !defined NODFA
590      else if (strcmp(argv[op], "-dfa") == 0) all_use_dfa = 1;
591    #endif
592    else if (strcmp(argv[op], "-o") == 0 && argc > 2 &&    else if (strcmp(argv[op], "-o") == 0 && argc > 2 &&
593        ((size_offsets = get_value((unsigned char *)argv[op+1], &endptr)),        ((size_offsets = get_value((unsigned char *)argv[op+1], &endptr)),
594          *endptr == 0))          *endptr == 0))
# Line 549  while (argc > 1 && argv[op][0] == '-') Line 616  while (argc > 1 && argv[op][0] == '-')
616      printf("  POSIX malloc threshold = %d\n", rc);      printf("  POSIX malloc threshold = %d\n", rc);
617      (void)pcre_config(PCRE_CONFIG_MATCH_LIMIT, &rc);      (void)pcre_config(PCRE_CONFIG_MATCH_LIMIT, &rc);
618      printf("  Default match limit = %d\n", rc);      printf("  Default match limit = %d\n", rc);
619        (void)pcre_config(PCRE_CONFIG_MATCH_LIMIT_RECURSION, &rc);
620        printf("  Default recursion depth limit = %d\n", rc);
621      (void)pcre_config(PCRE_CONFIG_STACKRECURSE, &rc);      (void)pcre_config(PCRE_CONFIG_STACKRECURSE, &rc);
622      printf("  Match recursion uses %s\n", rc? "stack" : "heap");      printf("  Match recursion uses %s\n", rc? "stack" : "heap");
623      exit(0);      exit(0);
# Line 558  while (argc > 1 && argv[op][0] == '-') Line 627  while (argc > 1 && argv[op][0] == '-')
627      printf("** Unknown or malformed option %s\n", argv[op]);      printf("** Unknown or malformed option %s\n", argv[op]);
628      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");
629      printf("  -C     show PCRE compile-time options and exit\n");      printf("  -C     show PCRE compile-time options and exit\n");
630      printf("  -d     debug: show compiled code; implies -i\n"      printf("  -d     debug: show compiled code; implies -i\n");
631             "  -i     show information about compiled pattern\n"  #if !defined NODFA
632        printf("  -dfa   force DFA matching for all subjects\n");
633    #endif
634        printf("  -i     show information about compiled pattern\n"
635             "  -m     output memory used information\n"             "  -m     output memory used information\n"
636             "  -o <n> set size of offsets vector to <n>\n");             "  -o <n> set size of offsets vector to <n>\n");
637  #if !defined NOPOSIX  #if !defined NOPOSIX
# Line 567  while (argc > 1 && argv[op][0] == '-') Line 639  while (argc > 1 && argv[op][0] == '-')
639  #endif  #endif
640      printf("  -s     output store (memory) used information\n"      printf("  -s     output store (memory) used information\n"
641             "  -t     time compilation and execution\n");             "  -t     time compilation and execution\n");
642      return 1;      yield = 1;
643        goto EXIT;
644      }      }
645    op++;    op++;
646    argc--;    argc--;
# Line 581  if (offsets == NULL) Line 654  if (offsets == NULL)
654    {    {
655    printf("** Failed to get %d bytes of memory for offsets vector\n",    printf("** Failed to get %d bytes of memory for offsets vector\n",
656      size_offsets_max * sizeof(int));      size_offsets_max * sizeof(int));
657    return 1;    yield = 1;
658      goto EXIT;
659    }    }
660    
661  /* Sort out the input and output files */  /* Sort out the input and output files */
# Line 592  if (argc > 1) Line 666  if (argc > 1)
666    if (infile == NULL)    if (infile == NULL)
667      {      {
668      printf("** Failed to open %s\n", argv[op]);      printf("** Failed to open %s\n", argv[op]);
669      return 1;      yield = 1;
670        goto EXIT;
671      }      }
672    }    }
673    
# Line 602  if (argc > 2) Line 677  if (argc > 2)
677    if (outfile == NULL)    if (outfile == NULL)
678      {      {
679      printf("** Failed to open %s\n", argv[op+1]);      printf("** Failed to open %s\n", argv[op+1]);
680      return 1;      yield = 1;
681        goto EXIT;
682      }      }
683    }    }
684    
# Line 613  pcre_free = new_free; Line 689  pcre_free = new_free;
689  pcre_stack_malloc = stack_malloc;  pcre_stack_malloc = stack_malloc;
690  pcre_stack_free = stack_free;  pcre_stack_free = stack_free;
691    
692  /* Heading line, then prompt for first regex if stdin */  /* Heading line unless quiet, then prompt for first regex if stdin */
693    
694  fprintf(outfile, "PCRE version %s\n\n", pcre_version());  if (!quiet) fprintf(outfile, "PCRE version %s\n\n", pcre_version());
695    
696  /* Main loop */  /* Main loop */
697    
# Line 802  while (!done) Line 878  while (!done)
878      {      {
879      switch (*pp++)      switch (*pp++)
880        {        {
881          case 'f': options |= PCRE_FIRSTLINE; break;
882        case 'g': do_g = 1; break;        case 'g': do_g = 1; break;
883        case 'i': options |= PCRE_CASELESS; break;        case 'i': options |= PCRE_CASELESS; break;
884        case 'm': options |= PCRE_MULTILINE; break;        case 'm': options |= PCRE_MULTILINE; break;
# Line 831  while (!done) Line 908  while (!done)
908    
909        case 'L':        case 'L':
910        ppp = pp;        ppp = pp;
911        while (*ppp != '\n' && *ppp != ' ') ppp++;        /* The '\r' test here is so that it works on Windows */
912          while (*ppp != '\n' && *ppp != '\r' && *ppp != ' ') ppp++;
913        *ppp = 0;        *ppp = 0;
914        if (setlocale(LC_CTYPE, (const char *)pp) == NULL)        if (setlocale(LC_CTYPE, (const char *)pp) == NULL)
915          {          {
# Line 849  while (!done) Line 927  while (!done)
927        *pp = 0;        *pp = 0;
928        break;        break;
929    
930        case '\n': case ' ': break;        case '\r':                      /* So that it works in Windows */
931          case '\n':
932          case ' ':
933          break;
934    
935        default:        default:
936        fprintf(outfile, "** Unknown option '%c'\n", pp[-1]);        fprintf(outfile, "** Unknown option '%c'\n", pp[-1]);
# Line 869  while (!done) Line 950  while (!done)
950    
951      if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE;      if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE;
952      if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE;      if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE;
953        if ((options & PCRE_DOTALL) != 0) cflags |= REG_DOTALL;
954        if ((options & PCRE_NO_AUTO_CAPTURE) != 0) cflags |= REG_NOSUB;
955        if ((options & PCRE_UTF8) != 0) cflags |= REG_UTF8;
956    
957      rc = regcomp(&preg, (char *)p, cflags);      rc = regcomp(&preg, (char *)p, cflags);
958    
959      /* Compilation failed; go back for another re, skipping to blank line      /* Compilation failed; go back for another re, skipping to blank line
# Line 1008  while (!done) Line 1093  while (!done)
1093      if (do_showinfo)      if (do_showinfo)
1094        {        {
1095        unsigned long int get_options, all_options;        unsigned long int get_options, all_options;
1096    #if !defined NOINFOCHECK
1097        int old_first_char, old_options, old_count;        int old_first_char, old_options, old_count;
1098    #endif
1099        int count, backrefmax, first_char, need_char;        int count, backrefmax, first_char, need_char;
1100        int nameentrysize, namecount;        int nameentrysize, namecount;
1101        const uschar *nametable;        const uschar *nametable;
# Line 1016  while (!done) Line 1103  while (!done)
1103        if (do_debug)        if (do_debug)
1104          {          {
1105          fprintf(outfile, "------------------------------------------------------------------\n");          fprintf(outfile, "------------------------------------------------------------------\n");
1106          print_internals(re, outfile);          pcre_printint(re, outfile);
1107          }          }
1108    
1109        new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options);        new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options);
# Line 1029  while (!done) Line 1116  while (!done)
1116        new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount);        new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount);
1117        new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable);        new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable);
1118    
1119    #if !defined NOINFOCHECK
1120        old_count = pcre_info(re, &old_options, &old_first_char);        old_count = pcre_info(re, &old_options, &old_first_char);
1121        if (count < 0) fprintf(outfile,        if (count < 0) fprintf(outfile,
1122          "Error %d from pcre_info()\n", count);          "Error %d from pcre_info()\n", count);
# Line 1046  while (!done) Line 1134  while (!done)
1134            "Options disagreement: pcre_fullinfo=%ld pcre_info=%d\n",            "Options disagreement: pcre_fullinfo=%ld pcre_info=%d\n",
1135              get_options, old_options);              get_options, old_options);
1136          }          }
1137    #endif
1138    
1139        if (size != regex_gotten_store) fprintf(outfile,        if (size != regex_gotten_store) fprintf(outfile,
1140          "Size disagreement: pcre_fullinfo=%d call to malloc for %d\n",          "Size disagreement: pcre_fullinfo=%d call to malloc for %d\n",
1141          size, regex_gotten_store);          (int)size, (int)regex_gotten_store);
1142    
1143        fprintf(outfile, "Capturing subpattern count = %d\n", count);        fprintf(outfile, "Capturing subpattern count = %d\n", count);
1144        if (backrefmax > 0)        if (backrefmax > 0)
# Line 1080  while (!done) Line 1169  while (!done)
1169          fprintf(outfile, "Partial matching not supported\n");          fprintf(outfile, "Partial matching not supported\n");
1170    
1171        if (get_options == 0) fprintf(outfile, "No options\n");        if (get_options == 0) fprintf(outfile, "No options\n");
1172          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%s\n",
1173            ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "",            ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "",
1174            ((get_options & PCRE_CASELESS) != 0)? " caseless" : "",            ((get_options & PCRE_CASELESS) != 0)? " caseless" : "",
1175            ((get_options & PCRE_EXTENDED) != 0)? " extended" : "",            ((get_options & PCRE_EXTENDED) != 0)? " extended" : "",
1176            ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "",            ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "",
1177              ((get_options & PCRE_FIRSTLINE) != 0)? " firstline" : "",
1178            ((get_options & PCRE_DOTALL) != 0)? " dotall" : "",            ((get_options & PCRE_DOTALL) != 0)? " dotall" : "",
1179            ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",            ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",
1180            ((get_options & PCRE_EXTRA) != 0)? " extra" : "",            ((get_options & PCRE_EXTRA) != 0)? " extra" : "",
1181            ((get_options & PCRE_UNGREEDY) != 0)? " ungreedy" : "",            ((get_options & PCRE_UNGREEDY) != 0)? " ungreedy" : "",
1182              ((get_options & PCRE_NO_AUTO_CAPTURE) != 0)? " no_auto_capture" : "",
1183            ((get_options & PCRE_UTF8) != 0)? " utf8" : "",            ((get_options & PCRE_UTF8) != 0)? " utf8" : "",
1184            ((get_options & PCRE_NO_UTF8_CHECK) != 0)? " no_utf8_check" : "");            ((get_options & PCRE_NO_UTF8_CHECK) != 0)? " no_utf8_check" : "");
1185    
# Line 1222  while (!done) Line 1313  while (!done)
1313            }            }
1314          fclose(f);          fclose(f);
1315          }          }
1316    
1317          new_free(re);
1318          if (extra != NULL) new_free(extra);
1319          if (tables != NULL) new_free((void *)tables);
1320        continue;  /* With next regex */        continue;  /* With next regex */
1321        }        }
1322      }        /* End of non-POSIX compile */      }        /* End of non-POSIX compile */
# Line 1230  while (!done) Line 1325  while (!done)
1325    
1326    for (;;)    for (;;)
1327      {      {
1328      unsigned char *q;      uschar *q;
1329      unsigned char *bptr = dbuffer;      uschar *bptr = dbuffer;
1330      int *use_offsets = offsets;      int *use_offsets = offsets;
1331      int use_size_offsets = size_offsets;      int use_size_offsets = size_offsets;
1332      int callout_data = 0;      int callout_data = 0;
# Line 1244  while (!done) Line 1339  while (!done)
1339      int gmatched = 0;      int gmatched = 0;
1340      int start_offset = 0;      int start_offset = 0;
1341      int g_notempty = 0;      int g_notempty = 0;
1342        int use_dfa = 0;
1343    
1344      options = 0;      options = 0;
1345    
# Line 1299  while (!done) Line 1395  while (!done)
1395    
1396          /* Handle \x{..} specially - new Perl thing for utf8 */          /* Handle \x{..} specially - new Perl thing for utf8 */
1397    
1398    #if !defined NOUTF8
1399          if (*p == '{')          if (*p == '{')
1400            {            {
1401            unsigned char *pt = p;            unsigned char *pt = p;
# Line 1317  while (!done) Line 1414  while (!done)
1414              }              }
1415            /* Not correct form; fall through */            /* Not correct form; fall through */
1416            }            }
1417    #endif
1418    
1419          /* Ordinary \x */          /* Ordinary \x */
1420    
# Line 1397  while (!done) Line 1495  while (!done)
1495            }            }
1496          continue;          continue;
1497    
1498    #if !defined NODFA
1499            case 'D':
1500    #if !defined NOPOSIX
1501            if (posix || do_posix)
1502              printf("** Can't use dfa matching in POSIX mode: \\D ignored\n");
1503            else
1504    #endif
1505              use_dfa = 1;
1506            continue;
1507    
1508            case 'F':
1509            options |= PCRE_DFA_SHORTEST;
1510            continue;
1511    #endif
1512    
1513          case 'G':          case 'G':
1514          if (isdigit(*p))          if (isdigit(*p))
1515            {            {
# Line 1439  while (!done) Line 1552  while (!done)
1552              {              {
1553              printf("** Failed to get %d bytes of memory for offsets vector\n",              printf("** Failed to get %d bytes of memory for offsets vector\n",
1554                size_offsets_max * sizeof(int));                size_offsets_max * sizeof(int));
1555              return 1;              yield = 1;
1556                goto EXIT;
1557              }              }
1558            }            }
1559          use_size_offsets = n;          use_size_offsets = n;
# Line 1450  while (!done) Line 1564  while (!done)
1564          options |= PCRE_PARTIAL;          options |= PCRE_PARTIAL;
1565          continue;          continue;
1566    
1567    #if !defined NODFA
1568            case 'R':
1569            options |= PCRE_DFA_RESTART;
1570            continue;
1571    #endif
1572    
1573          case 'S':          case 'S':
1574          show_malloc = 1;          show_malloc = 1;
1575          continue;          continue;
# Line 1467  while (!done) Line 1587  while (!done)
1587      *q = 0;      *q = 0;
1588      len = q - dbuffer;      len = q - dbuffer;
1589    
1590        if ((all_use_dfa || use_dfa) && find_match_limit)
1591          {
1592          printf("**Match limit not relevant for DFA matching: ignored\n");
1593          find_match_limit = 0;
1594          }
1595    
1596      /* Handle matching via the POSIX interface, which does not      /* Handle matching via the POSIX interface, which does not
1597      support timing or playing with the match limit or callout data. */      support timing or playing with the match limit or callout data. */
1598    
# Line 1488  while (!done) Line 1614  while (!done)
1614          (void)regerror(rc, &preg, (char *)buffer, BUFFER_SIZE);          (void)regerror(rc, &preg, (char *)buffer, BUFFER_SIZE);
1615          fprintf(outfile, "No match: POSIX code %d: %s\n", rc, buffer);          fprintf(outfile, "No match: POSIX code %d: %s\n", rc, buffer);
1616          }          }
1617          else if ((((const pcre *)preg.re_pcre)->options & PCRE_NO_AUTO_CAPTURE)
1618                  != 0)
1619            {
1620            fprintf(outfile, "Matched with REG_NOSUB\n");
1621            }
1622        else        else
1623          {          {
1624          size_t i;          size_t i;
# Line 1524  while (!done) Line 1655  while (!done)
1655          register int i;          register int i;
1656          clock_t time_taken;          clock_t time_taken;
1657          clock_t start_time = clock();          clock_t start_time = clock();
1658    
1659    #if !defined NODFA
1660            if (all_use_dfa || use_dfa)
1661              {
1662              int workspace[1000];
1663              for (i = 0; i < LOOPREPEAT; i++)
1664                count = pcre_dfa_exec(re, NULL, (char *)bptr, len, start_offset,
1665                  options | g_notempty, use_offsets, use_size_offsets, workspace,
1666                  sizeof(workspace)/sizeof(int));
1667              }
1668            else
1669    #endif
1670    
1671          for (i = 0; i < LOOPREPEAT; i++)          for (i = 0; i < LOOPREPEAT; i++)
1672            count = pcre_exec(re, extra, (char *)bptr, len,            count = pcre_exec(re, extra, (char *)bptr, len,
1673              start_offset, options | g_notempty, use_offsets, use_size_offsets);              start_offset, options | g_notempty, use_offsets, use_size_offsets);
1674    
1675          time_taken = clock() - start_time;          time_taken = clock() - start_time;
1676          fprintf(outfile, "Execute time %.3f milliseconds\n",          fprintf(outfile, "Execute time %.3f milliseconds\n",
1677            (((double)time_taken * 1000.0) / (double)LOOPREPEAT) /            (((double)time_taken * 1000.0) / (double)LOOPREPEAT) /
# Line 1534  while (!done) Line 1679  while (!done)
1679          }          }
1680    
1681        /* If find_match_limit is set, we want to do repeated matches with        /* If find_match_limit is set, we want to do repeated matches with
1682        varying limits in order to find the minimum value. */        varying limits in order to find the minimum value for the match limit and
1683          for the recursion limit. */
1684    
1685        if (find_match_limit)        if (find_match_limit)
1686          {          {
         int min = 0;  
         int mid = 64;  
         int max = -1;  
   
1687          if (extra == NULL)          if (extra == NULL)
1688            {            {
1689            extra = (pcre_extra *)malloc(sizeof(pcre_extra));            extra = (pcre_extra *)malloc(sizeof(pcre_extra));
1690            extra->flags = 0;            extra->flags = 0;
1691            }            }
         extra->flags |= PCRE_EXTRA_MATCH_LIMIT;  
1692    
1693          for (;;)          count = check_match_limit(re, extra, bptr, len, start_offset,
1694            {            options|g_notempty, use_offsets, use_size_offsets,
1695            extra->match_limit = mid;            PCRE_EXTRA_MATCH_LIMIT, &(extra->match_limit),
1696            count = pcre_exec(re, extra, (char *)bptr, len, start_offset,            PCRE_ERROR_MATCHLIMIT, "match()");
1697              options | g_notempty, use_offsets, use_size_offsets);  
1698            if (count == PCRE_ERROR_MATCHLIMIT)          count = check_match_limit(re, extra, bptr, len, start_offset,
1699              {            options|g_notempty, use_offsets, use_size_offsets,
1700              /* fprintf(outfile, "Testing match limit = %d\n", mid); */            PCRE_EXTRA_MATCH_LIMIT_RECURSION, &(extra->match_limit_recursion),
1701              min = mid;            PCRE_ERROR_RECURSIONLIMIT, "match() recursion");
             mid = (mid == max - 1)? max : (max > 0)? (min + max)/2 : mid*2;  
             }  
           else if (count >= 0 || count == PCRE_ERROR_NOMATCH ||  
                                  count == PCRE_ERROR_PARTIAL)  
             {  
             if (mid == min + 1)  
               {  
               fprintf(outfile, "Minimum match limit = %d\n", mid);  
               break;  
               }  
             /* fprintf(outfile, "Testing match limit = %d\n", mid); */  
             max = mid;  
             mid = (min + mid)/2;  
             }  
           else break;    /* Some other error */  
           }  
   
         extra->flags &= ~PCRE_EXTRA_MATCH_LIMIT;  
1702          }          }
1703    
1704        /* If callout_data is set, use the interface with additional data */        /* If callout_data is set, use the interface with additional data */
# Line 1597  while (!done) Line 1720  while (!done)
1720        /* 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
1721        value of match_limit. */        value of match_limit. */
1722    
1723        else  #if !defined NODFA
1724          else if (all_use_dfa || use_dfa)
1725          {          {
1726          count = pcre_exec(re, extra, (char *)bptr, len,          int workspace[1000];
1727            start_offset, options | g_notempty, use_offsets, use_size_offsets);          count = pcre_dfa_exec(re, NULL, (char *)bptr, len, start_offset,
1728              options | g_notempty, use_offsets, use_size_offsets, workspace,
1729              sizeof(workspace)/sizeof(int));
1730            if (count == 0)
1731              {
1732              fprintf(outfile, "Matched, but too many subsidiary matches\n");
1733              count = use_size_offsets/2;
1734              }
1735          }          }
1736    #endif
1737    
1738        if (count == 0)        else
1739          {          {
1740          fprintf(outfile, "Matched, but too many substrings\n");          count = pcre_exec(re, extra, (char *)bptr, len,
1741          count = use_size_offsets/3;            start_offset, options | g_notempty, use_offsets, use_size_offsets);
1742            if (count == 0)
1743              {
1744              fprintf(outfile, "Matched, but too many substrings\n");
1745              count = use_size_offsets/3;
1746              }
1747          }          }
1748    
1749        /* Matched */        /* Matched */
# Line 1692  while (!done) Line 1829  while (!done)
1829    
1830        else if (count == PCRE_ERROR_PARTIAL)        else if (count == PCRE_ERROR_PARTIAL)
1831          {          {
1832          fprintf(outfile, "Partial match\n");          fprintf(outfile, "Partial match");
1833    #if !defined NODFA
1834            if ((all_use_dfa || use_dfa) && use_size_offsets > 2)
1835              fprintf(outfile, ": %.*s", use_offsets[1] - use_offsets[0],
1836                bptr + use_offsets[0]);
1837    #endif
1838            fprintf(outfile, "\n");
1839          break;  /* Out of the /g loop */          break;  /* Out of the /g loop */
1840          }          }
1841    
# Line 1770  while (!done) Line 1913  while (!done)
1913    if (posix || do_posix) regfree(&preg);    if (posix || do_posix) regfree(&preg);
1914  #endif  #endif
1915    
1916    if (re != NULL) free(re);    if (re != NULL) new_free(re);
1917    if (extra != NULL) free(extra);    if (extra != NULL) new_free(extra);
1918    if (tables != NULL)    if (tables != NULL)
1919      {      {
1920      free((void *)tables);      new_free((void *)tables);
1921      setlocale(LC_CTYPE, "C");      setlocale(LC_CTYPE, "C");
1922      }      }
1923    }    }
1924    
1925  if (infile == stdin) fprintf(outfile, "\n");  if (infile == stdin) fprintf(outfile, "\n");
1926  return 0;  
1927    EXIT:
1928    
1929    if (infile != NULL && infile != stdin) fclose(infile);
1930    if (outfile != NULL && outfile != stdout) fclose(outfile);
1931    
1932    free(buffer);
1933    free(dbuffer);
1934    free(pbuffer);
1935    free(offsets);
1936    
1937    return yield;
1938  }  }
1939    
1940  /* End */  /* End of pcretest.c */

Legend:
Removed from v.75  
changed lines
  Added in v.87

  ViewVC Help
Powered by ViewVC 1.1.5