/[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 91 by nigel, Sat Feb 24 21:41:34 2007 UTC revision 361 by ph10, Thu Jul 10 16:03:28 2008 UTC
# Line 36  POSSIBILITY OF SUCH DAMAGE. Line 36  POSSIBILITY OF SUCH DAMAGE.
36  */  */
37    
38    
39    #ifdef HAVE_CONFIG_H
40    #include "config.h"
41    #endif
42    
43  #include <ctype.h>  #include <ctype.h>
44  #include <stdio.h>  #include <stdio.h>
45  #include <string.h>  #include <string.h>
# Line 44  POSSIBILITY OF SUCH DAMAGE. Line 48  POSSIBILITY OF SUCH DAMAGE.
48  #include <locale.h>  #include <locale.h>
49  #include <errno.h>  #include <errno.h>
50    
51  #ifndef _WIN32  #ifdef SUPPORT_LIBREADLINE
52  #include <sys/resource.h>  #ifdef HAVE_UNISTD_H
53    #include <unistd.h>
54    #endif
55    #include <readline/readline.h>
56    #include <readline/history.h>
57  #endif  #endif
58    
 #define PCRE_SPY        /* For Win32 build, import data, not export */  
59    
60  /* We include pcre_internal.h because we need the internal info for displaying  /* A number of things vary for Windows builds. Originally, pcretest opened its
61  the results of pcre_study() and we also need to know about the internal  input and output without "b"; then I was told that "b" was needed in some
62  macros, structures, and other internal data values; pcretest has "inside  environments, so it was added for release 5.0 to both the input and output. (It
63  information" compared to a program that strictly follows the PCRE API. */  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    #define isatty _isatty         /* This is what Windows calls them, I'm told */
75    #define fileno _fileno
76    
77    #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    #endif
83    
84    
85    /* 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    
90    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    
94    #include "pcre.h"
95  #include "pcre_internal.h"  #include "pcre_internal.h"
96    
97  /* We need access to the data tables that PCRE uses. So as not to have to keep  /* We need access to some of the data tables that PCRE uses. So as not to have
98  two copies, we include the source file here, changing the names of the external  to keep two copies, we include the source file here, changing the names of the
99  symbols to prevent clashes. */  external symbols to prevent clashes. */
100    
101    #define _pcre_ucp_gentype      ucp_gentype
102  #define _pcre_utf8_table1      utf8_table1  #define _pcre_utf8_table1      utf8_table1
103  #define _pcre_utf8_table1_size utf8_table1_size  #define _pcre_utf8_table1_size utf8_table1_size
104  #define _pcre_utf8_table2      utf8_table2  #define _pcre_utf8_table2      utf8_table2
# Line 68  symbols to prevent clashes. */ Line 106  symbols to prevent clashes. */
106  #define _pcre_utf8_table4      utf8_table4  #define _pcre_utf8_table4      utf8_table4
107  #define _pcre_utt              utt  #define _pcre_utt              utt
108  #define _pcre_utt_size         utt_size  #define _pcre_utt_size         utt_size
109    #define _pcre_utt_names        utt_names
110  #define _pcre_OP_lengths       OP_lengths  #define _pcre_OP_lengths       OP_lengths
111    
112  #include "pcre_tables.c"  #include "pcre_tables.c"
113    
114  /* We also need the pcre_printint() function for printing out compiled  /* We also need the pcre_printint() function for printing out compiled
115  patterns. This function is in a separate file so that it can be included in  patterns. This function is in a separate file so that it can be included in
116  pcre_compile.c when that module is compiled with debugging enabled. */  pcre_compile.c when that module is compiled with debugging enabled.
117    
118    The definition of the macro PRINTABLE, which determines whether to print an
119    output character as-is or as a hex value when showing compiled patterns, is
120    contained in this file. We uses it here also, in cases when the locale has not
121    been explicitly changed, so as to get consistent output from systems that
122    differ in their output from isprint() even in the "C" locale. */
123    
124  #include "pcre_printint.src"  #include "pcre_printint.src"
125    
126    #define PRINTHEX(c) (locale_set? isprint(c) : PRINTABLE(c))
127    
128    
129  /* It is possible to compile this test program without including support for  /* It is possible to compile this test program without including support for
130  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 87  Makefile. */ Line 134  Makefile. */
134  #include "pcreposix.h"  #include "pcreposix.h"
135  #endif  #endif
136    
137  /* It is also possible, for the benefit of the version imported into Exim, to  /* It is also possible, for the benefit of the version currently imported into
138  build pcretest without support for UTF8 (define NOUTF8), without the interface  Exim, to build pcretest without support for UTF8 (define NOUTF8), without the
139  to the DFA matcher (NODFA), and without the doublecheck of the old "info"  interface to the DFA matcher (NODFA), and without the doublecheck of the old
140  function (define NOINFOCHECK). */  "info" function (define NOINFOCHECK). In fact, we automatically cut out the
141    UTF8 support if PCRE is built without it. */
142    
143    #ifndef SUPPORT_UTF8
144    #ifndef NOUTF8
145    #define NOUTF8
146    #endif
147    #endif
148    
149    
150  /* Other parameters */  /* Other parameters */
# Line 103  function (define NOINFOCHECK). */ Line 157  function (define NOINFOCHECK). */
157  #endif  #endif
158  #endif  #endif
159    
160    /* This is the default loop count for timing. */
161    
162  #define LOOPREPEAT 500000  #define LOOPREPEAT 500000
163    
164  /* Static variables */  /* Static variables */
# Line 113  static int callout_count; Line 169  static int callout_count;
169  static int callout_extra;  static int callout_extra;
170  static int callout_fail_count;  static int callout_fail_count;
171  static int callout_fail_id;  static int callout_fail_id;
172    static int debug_lengths;
173  static int first_callout;  static int first_callout;
174    static int locale_set = 0;
175  static int show_malloc;  static int show_malloc;
176  static int use_utf8;  static int use_utf8;
177  static size_t gotten_store;  static size_t gotten_store;
# Line 143  optimal way of handling this, but hey, t Line 201  optimal way of handling this, but hey, t
201  Arguments:  Arguments:
202    f            the file to read    f            the file to read
203    start        where in buffer to start (this *must* be within buffer)    start        where in buffer to start (this *must* be within buffer)
204      prompt       for stdin or readline()
205    
206  Returns:       pointer to the start of new data  Returns:       pointer to the start of new data
207                 could be a copy of start, or could be moved                 could be a copy of start, or could be moved
# Line 150  Returns:       pointer to the start of n Line 209  Returns:       pointer to the start of n
209  */  */
210    
211  static uschar *  static uschar *
212  extend_inputline(FILE *f, uschar *start)  extend_inputline(FILE *f, uschar *start, const char *prompt)
213  {  {
214  uschar *here = start;  uschar *here = start;
215    
216  for (;;)  for (;;)
217    {    {
218    int rlen = buffer_size - (here - buffer);    int rlen = buffer_size - (here - buffer);
219    
220    if (rlen > 1000)    if (rlen > 1000)
221      {      {
222      int dlen;      int dlen;
223      if (fgets((char *)here, rlen,  f) == NULL)  
224        return (here == start)? NULL : start;      /* If libreadline support is required, use readline() to read a line if the
225        input is a terminal. Note that readline() removes the trailing newline, so
226        we must put it back again, to be compatible with fgets(). */
227    
228    #ifdef SUPPORT_LIBREADLINE
229        if (isatty(fileno(f)))
230          {
231          size_t len;
232          char *s = readline(prompt);
233          if (s == NULL) return (here == start)? NULL : start;
234          len = strlen(s);
235          if (len > 0) add_history(s);
236          if (len > rlen - 1) len = rlen - 1;
237          memcpy(here, s, len);
238          here[len] = '\n';
239          here[len+1] = 0;
240          free(s);
241          }
242        else
243    #endif
244    
245        /* Read the next line by normal means, prompting if the file is stdin. */
246    
247          {
248          if (f == stdin) printf(prompt);
249          if (fgets((char *)here, rlen,  f) == NULL)
250            return (here == start)? NULL : start;
251          }
252    
253      dlen = (int)strlen((char *)here);      dlen = (int)strlen((char *)here);
254      if (dlen > 0 && here[dlen - 1] == '\n') return start;      if (dlen > 0 && here[dlen - 1] == '\n') return start;
255      here += dlen;      here += dlen;
# Line 213  return NULL;  /* Control never gets here Line 301  return NULL;  /* Control never gets here
301    
302  /* We don't use strtoul() because SunOS4 doesn't have it. Rather than mess  /* We don't use strtoul() because SunOS4 doesn't have it. Rather than mess
303  around with conditional compilation, just do the job by hand. It is only used  around with conditional compilation, just do the job by hand. It is only used
304  for unpicking the -o argument, so just keep it simple.  for unpicking arguments, so just keep it simple.
305    
306  Arguments:  Arguments:
307    str           string to be converted    str           string to be converted
# Line 311  Arguments: Line 399  Arguments:
399  Returns:     number of characters placed in the buffer  Returns:     number of characters placed in the buffer
400  */  */
401    
402    #if !defined NOUTF8
403    
404  static int  static int
405  ord2utf8(int cvalue, uschar *utf8bytes)  ord2utf8(int cvalue, uschar *utf8bytes)
406  {  {
# Line 327  for (j = i; j > 0; j--) Line 417  for (j = i; j > 0; j--)
417  return i + 1;  return i + 1;
418  }  }
419    
420    #endif
421    
422    
423    
424  /*************************************************  /*************************************************
# Line 353  while (length-- > 0) Line 445  while (length-- > 0)
445        {        {
446        length -= rc - 1;        length -= rc - 1;
447        p += rc;        p += rc;
448        if (c < 256 && isprint(c))        if (PRINTHEX(c))
449          {          {
450          if (f != NULL) fprintf(f, "%c", c);          if (f != NULL) fprintf(f, "%c", c);
451          yield++;          yield++;
452          }          }
453        else        else
454          {          {
455          int n;          int n = 4;
456          if (f != NULL) fprintf(f, "\\x{%02x}%n", c, &n);          if (f != NULL) fprintf(f, "\\x{%02x}", c);
457          yield += n;          yield += (n <= 0x000000ff)? 2 :
458                     (n <= 0x00000fff)? 3 :
459                     (n <= 0x0000ffff)? 4 :
460                     (n <= 0x000fffff)? 5 : 6;
461          }          }
462        continue;        continue;
463        }        }
# Line 371  while (length-- > 0) Line 466  while (length-- > 0)
466    
467     /* Not UTF-8, or malformed UTF-8  */     /* Not UTF-8, or malformed UTF-8  */
468    
469    if (isprint(c = *(p++)))    c = *p++;
470      if (PRINTHEX(c))
471      {      {
472      if (f != NULL) fprintf(f, "%c", c);      if (f != NULL) fprintf(f, "%c", c);
473      yield++;      yield++;
# Line 610  return count; Line 706  return count;
706    
707    
708  /*************************************************  /*************************************************
709    *         Case-independent strncmp() function    *
710    *************************************************/
711    
712    /*
713    Arguments:
714      s         first string
715      t         second string
716      n         number of characters to compare
717    
718    Returns:    < 0, = 0, or > 0, according to the comparison
719    */
720    
721    static int
722    strncmpic(uschar *s, uschar *t, int n)
723    {
724    while (n--)
725      {
726      int c = tolower(*s++) - tolower(*t++);
727      if (c) return c;
728      }
729    return 0;
730    }
731    
732    
733    
734    /*************************************************
735  *         Check newline indicator                *  *         Check newline indicator                *
736  *************************************************/  *************************************************/
737    
738  /* This is used both at compile and run-time to check for <xxx> escapes, where  /* This is used both at compile and run-time to check for <xxx> escapes, where
739  xxx is LF, CR, or CRLF. Print a message and return 0 if there is no match.  xxx is LF, CR, CRLF, ANYCRLF, or ANY. Print a message and return 0 if there is
740    no match.
741    
742  Arguments:  Arguments:
743    p           points after the leading '<'    p           points after the leading '<'
# Line 626  Returns:      appropriate PCRE_NEWLINE_x Line 749  Returns:      appropriate PCRE_NEWLINE_x
749  static int  static int
750  check_newline(uschar *p, FILE *f)  check_newline(uschar *p, FILE *f)
751  {  {
752  if (strncmp((char *)p, "cr>", 3) == 0) return PCRE_NEWLINE_CR;  if (strncmpic(p, (uschar *)"cr>", 3) == 0) return PCRE_NEWLINE_CR;
753  if (strncmp((char *)p, "lf>", 3) == 0) return PCRE_NEWLINE_LF;  if (strncmpic(p, (uschar *)"lf>", 3) == 0) return PCRE_NEWLINE_LF;
754  if (strncmp((char *)p, "crlf>", 5) == 0) return PCRE_NEWLINE_CRLF;  if (strncmpic(p, (uschar *)"crlf>", 5) == 0) return PCRE_NEWLINE_CRLF;
755    if (strncmpic(p, (uschar *)"anycrlf>", 8) == 0) return PCRE_NEWLINE_ANYCRLF;
756    if (strncmpic(p, (uschar *)"any>", 4) == 0) return PCRE_NEWLINE_ANY;
757    if (strncmpic(p, (uschar *)"bsr_anycrlf>", 12) == 0) return PCRE_BSR_ANYCRLF;
758    if (strncmpic(p, (uschar *)"bsr_unicode>", 12) == 0) return PCRE_BSR_UNICODE;
759  fprintf(f, "Unknown newline type at: <%s\n", p);  fprintf(f, "Unknown newline type at: <%s\n", p);
760  return 0;  return 0;
761  }  }
# Line 636  return 0; Line 763  return 0;
763    
764    
765  /*************************************************  /*************************************************
766    *             Usage function                     *
767    *************************************************/
768    
769    static void
770    usage(void)
771    {
772    printf("Usage:     pcretest [options] [<input file> [<output file>]]\n\n");
773    printf("Input and output default to stdin and stdout.\n");
774    #ifdef SUPPORT_LIBREADLINE
775    printf("If input is a terminal, readline() is used to read from it.\n");
776    #else
777    printf("This version of pcretest is not linked with readline().\n");
778    #endif
779    printf("\nOptions:\n");
780    printf("  -b       show compiled code (bytecode)\n");
781    printf("  -C       show PCRE compile-time options and exit\n");
782    printf("  -d       debug: show compiled code and information (-b and -i)\n");
783    #if !defined NODFA
784    printf("  -dfa     force DFA matching for all subjects\n");
785    #endif
786    printf("  -help    show usage information\n");
787    printf("  -i       show information about compiled patterns\n"
788           "  -m       output memory used information\n"
789           "  -o <n>   set size of offsets vector to <n>\n");
790    #if !defined NOPOSIX
791    printf("  -p       use POSIX interface\n");
792    #endif
793    printf("  -q       quiet: do not output PCRE version number at start\n");
794    printf("  -S <n>   set stack size to <n> megabytes\n");
795    printf("  -s       output store (memory) used information\n"
796           "  -t       time compilation and execution\n");
797    printf("  -t <n>   time compilation and execution, repeating <n> times\n");
798    printf("  -tm      time execution (matching) only\n");
799    printf("  -tm <n>  time execution (matching) only, repeating <n> times\n");
800    }
801    
802    
803    
804    /*************************************************
805  *                Main Program                    *  *                Main Program                    *
806  *************************************************/  *************************************************/
807    
# Line 650  int options = 0; Line 816  int options = 0;
816  int study_options = 0;  int study_options = 0;
817  int op = 1;  int op = 1;
818  int timeit = 0;  int timeit = 0;
819    int timeitm = 0;
820  int showinfo = 0;  int showinfo = 0;
821  int showstore = 0;  int showstore = 0;
822  int quiet = 0;  int quiet = 0;
# Line 681  buffer = (unsigned char *)malloc(buffer_ Line 848  buffer = (unsigned char *)malloc(buffer_
848  dbuffer = (unsigned char *)malloc(buffer_size);  dbuffer = (unsigned char *)malloc(buffer_size);
849  pbuffer = (unsigned char *)malloc(buffer_size);  pbuffer = (unsigned char *)malloc(buffer_size);
850    
851  /* The outfile variable is static so that new_malloc can use it. The _setmode()  /* The outfile variable is static so that new_malloc can use it. */
 stuff is some magic that I don't understand, but which apparently does good  
 things in Windows. It's related to line terminations.  */  
   
 #if defined(_WIN32) || defined(WIN32)  
 _setmode( _fileno( stdout ), 0x8000 );  
 #endif  /* defined(_WIN32) || defined(WIN32) */  
852    
853  outfile = stdout;  outfile = stdout;
854    
855    /* The following  _setmode() stuff is some Windows magic that tells its runtime
856    library to translate CRLF into a single LF character. At least, that's what
857    I've been told: never having used Windows I take this all on trust. Originally
858    it set 0x8000, but then I was advised that _O_BINARY was better. */
859    
860    #if defined(_WIN32) || defined(WIN32)
861    _setmode( _fileno( stdout ), _O_BINARY );
862    #endif
863    
864  /* Scan options */  /* Scan options */
865    
866  while (argc > 1 && argv[op][0] == '-')  while (argc > 1 && argv[op][0] == '-')
# Line 699  while (argc > 1 && argv[op][0] == '-') Line 869  while (argc > 1 && argv[op][0] == '-')
869    
870    if (strcmp(argv[op], "-s") == 0 || strcmp(argv[op], "-m") == 0)    if (strcmp(argv[op], "-s") == 0 || strcmp(argv[op], "-m") == 0)
871      showstore = 1;      showstore = 1;
   else if (strcmp(argv[op], "-t") == 0) timeit = 1;  
872    else if (strcmp(argv[op], "-q") == 0) quiet = 1;    else if (strcmp(argv[op], "-q") == 0) quiet = 1;
873      else if (strcmp(argv[op], "-b") == 0) debug = 1;
874    else if (strcmp(argv[op], "-i") == 0) showinfo = 1;    else if (strcmp(argv[op], "-i") == 0) showinfo = 1;
875    else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1;    else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1;
876  #if !defined NODFA  #if !defined NODFA
# Line 713  while (argc > 1 && argv[op][0] == '-') Line 883  while (argc > 1 && argv[op][0] == '-')
883      op++;      op++;
884      argc--;      argc--;
885      }      }
886      else if (strcmp(argv[op], "-t") == 0 || strcmp(argv[op], "-tm") == 0)
887        {
888        int both = argv[op][2] == 0;
889        int temp;
890        if (argc > 2 && (temp = get_value((unsigned char *)argv[op+1], &endptr),
891                         *endptr == 0))
892          {
893          timeitm = temp;
894          op++;
895          argc--;
896          }
897        else timeitm = LOOPREPEAT;
898        if (both) timeit = timeitm;
899        }
900    else if (strcmp(argv[op], "-S") == 0 && argc > 2 &&    else if (strcmp(argv[op], "-S") == 0 && argc > 2 &&
901        ((stack_size = get_value((unsigned char *)argv[op+1], &endptr)),        ((stack_size = get_value((unsigned char *)argv[op+1], &endptr)),
902          *endptr == 0))          *endptr == 0))
903      {      {
904  #ifdef _WIN32  #if defined(_WIN32) || defined(WIN32)
905      printf("PCRE: -S not supported on this OS\n");      printf("PCRE: -S not supported on this OS\n");
906      exit(1);      exit(1);
907  #else  #else
# Line 749  while (argc > 1 && argv[op][0] == '-') Line 933  while (argc > 1 && argv[op][0] == '-')
933      printf("  %sUnicode properties support\n", rc? "" : "No ");      printf("  %sUnicode properties support\n", rc? "" : "No ");
934      (void)pcre_config(PCRE_CONFIG_NEWLINE, &rc);      (void)pcre_config(PCRE_CONFIG_NEWLINE, &rc);
935      printf("  Newline sequence is %s\n", (rc == '\r')? "CR" :      printf("  Newline sequence is %s\n", (rc == '\r')? "CR" :
936        (rc == '\n')? "LF" : "CRLF");        (rc == '\n')? "LF" : (rc == ('\r'<<8 | '\n'))? "CRLF" :
937          (rc == -2)? "ANYCRLF" :
938          (rc == -1)? "ANY" : "???");
939        (void)pcre_config(PCRE_CONFIG_BSR, &rc);
940        printf("  \\R matches %s\n", rc? "CR, LF, or CRLF only" :
941                                         "all Unicode newlines");
942      (void)pcre_config(PCRE_CONFIG_LINK_SIZE, &rc);      (void)pcre_config(PCRE_CONFIG_LINK_SIZE, &rc);
943      printf("  Internal link size = %d\n", rc);      printf("  Internal link size = %d\n", rc);
944      (void)pcre_config(PCRE_CONFIG_POSIX_MALLOC_THRESHOLD, &rc);      (void)pcre_config(PCRE_CONFIG_POSIX_MALLOC_THRESHOLD, &rc);
# Line 760  while (argc > 1 && argv[op][0] == '-') Line 949  while (argc > 1 && argv[op][0] == '-')
949      printf("  Default recursion depth limit = %d\n", rc);      printf("  Default recursion depth limit = %d\n", rc);
950      (void)pcre_config(PCRE_CONFIG_STACKRECURSE, &rc);      (void)pcre_config(PCRE_CONFIG_STACKRECURSE, &rc);
951      printf("  Match recursion uses %s\n", rc? "stack" : "heap");      printf("  Match recursion uses %s\n", rc? "stack" : "heap");
952      exit(0);      goto EXIT;
953        }
954      else if (strcmp(argv[op], "-help") == 0 ||
955               strcmp(argv[op], "--help") == 0)
956        {
957        usage();
958        goto EXIT;
959      }      }
960    else    else
961      {      {
962      printf("** Unknown or malformed option %s\n", argv[op]);      printf("** Unknown or malformed option %s\n", argv[op]);
963      printf("Usage:   pcretest [options] [<input> [<output>]]\n");      usage();
     printf("  -C     show PCRE compile-time options and exit\n");  
     printf("  -d     debug: show compiled code; implies -i\n");  
 #if !defined NODFA  
     printf("  -dfa   force DFA matching for all subjects\n");  
 #endif  
     printf("  -i     show information about compiled pattern\n"  
            "  -m     output memory used information\n"  
            "  -o <n> set size of offsets vector to <n>\n");  
 #if !defined NOPOSIX  
     printf("  -p     use POSIX interface\n");  
 #endif  
     printf("  -S <n> set stack size to <n> megabytes\n");  
     printf("  -s     output store (memory) used information\n"  
            "  -t     time compilation and execution\n");  
964      yield = 1;      yield = 1;
965      goto EXIT;      goto EXIT;
966      }      }
# Line 794  offsets = (int *)malloc(size_offsets_max Line 975  offsets = (int *)malloc(size_offsets_max
975  if (offsets == NULL)  if (offsets == NULL)
976    {    {
977    printf("** Failed to get %d bytes of memory for offsets vector\n",    printf("** Failed to get %d bytes of memory for offsets vector\n",
978      size_offsets_max * sizeof(int));      (int)(size_offsets_max * sizeof(int)));
979    yield = 1;    yield = 1;
980    goto EXIT;    goto EXIT;
981    }    }
# Line 803  if (offsets == NULL) Line 984  if (offsets == NULL)
984    
985  if (argc > 1)  if (argc > 1)
986    {    {
987    infile = fopen(argv[op], "rb");    infile = fopen(argv[op], INPUT_MODE);
988    if (infile == NULL)    if (infile == NULL)
989      {      {
990      printf("** Failed to open %s\n", argv[op]);      printf("** Failed to open %s\n", argv[op]);
# Line 814  if (argc > 1) Line 995  if (argc > 1)
995    
996  if (argc > 2)  if (argc > 2)
997    {    {
998    outfile = fopen(argv[op+1], "wb");    outfile = fopen(argv[op+1], OUTPUT_MODE);
999    if (outfile == NULL)    if (outfile == NULL)
1000      {      {
1001      printf("** Failed to open %s\n", argv[op+1]);      printf("** Failed to open %s\n", argv[op+1]);
# Line 859  while (!done) Line 1040  while (!done)
1040    int do_showinfo = showinfo;    int do_showinfo = showinfo;
1041    int do_showrest = 0;    int do_showrest = 0;
1042    int do_flip = 0;    int do_flip = 0;
1043    int erroroffset, len, delimiter;    int erroroffset, len, delimiter, poffset;
1044    
1045    use_utf8 = 0;    use_utf8 = 0;
1046      debug_lengths = 1;
1047    
1048    if (infile == stdin) printf("  re> ");    if (extend_inputline(infile, buffer, "  re> ") == NULL) break;
   if (extend_inputline(infile, buffer) == NULL) break;  
1049    if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);    if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);
1050    fflush(outfile);    fflush(outfile);
1051    
# Line 964  while (!done) Line 1145  while (!done)
1145    
1146    if (isalnum(delimiter) || delimiter == '\\')    if (isalnum(delimiter) || delimiter == '\\')
1147      {      {
1148      fprintf(outfile, "** Delimiter must not be alphameric or \\\n");      fprintf(outfile, "** Delimiter must not be alphanumeric or \\\n");
1149      goto SKIP_DATA;      goto SKIP_DATA;
1150      }      }
1151    
1152    pp = p;    pp = p;
1153      poffset = p - buffer;
1154    
1155    for(;;)    for(;;)
1156      {      {
# Line 979  while (!done) Line 1161  while (!done)
1161        pp++;        pp++;
1162        }        }
1163      if (*pp != 0) break;      if (*pp != 0) break;
1164      if (infile == stdin) printf("    > ");      if ((pp = extend_inputline(infile, pp, "    > ")) == NULL)
     if ((pp = extend_inputline(infile, pp)) == NULL)  
1165        {        {
1166        fprintf(outfile, "** Unexpected EOF\n");        fprintf(outfile, "** Unexpected EOF\n");
1167        done = 1;        done = 1;
# Line 989  while (!done) Line 1170  while (!done)
1170      if (infile != stdin) fprintf(outfile, "%s", (char *)pp);      if (infile != stdin) fprintf(outfile, "%s", (char *)pp);
1171      }      }
1172    
1173      /* The buffer may have moved while being extended; reset the start of data
1174      pointer to the correct relative point in the buffer. */
1175    
1176      p = buffer + poffset;
1177    
1178    /* If the first character after the delimiter is backslash, make    /* If the first character after the delimiter is backslash, make
1179    the pattern end with backslash. This is purely to provide a way    the pattern end with backslash. This is purely to provide a way
1180    of testing for the error message when a pattern ends with backslash. */    of testing for the error message when a pattern ends with backslash. */
# Line 1020  while (!done) Line 1206  while (!done)
1206    
1207        case '+': do_showrest = 1; break;        case '+': do_showrest = 1; break;
1208        case 'A': options |= PCRE_ANCHORED; break;        case 'A': options |= PCRE_ANCHORED; break;
1209          case 'B': do_debug = 1; break;
1210        case 'C': options |= PCRE_AUTO_CALLOUT; break;        case 'C': options |= PCRE_AUTO_CALLOUT; break;
1211        case 'D': do_debug = do_showinfo = 1; break;        case 'D': do_debug = do_showinfo = 1; break;
1212        case 'E': options |= PCRE_DOLLAR_ENDONLY; break;        case 'E': options |= PCRE_DOLLAR_ENDONLY; break;
# Line 1037  while (!done) Line 1224  while (!done)
1224        case 'S': do_study = 1; break;        case 'S': do_study = 1; break;
1225        case 'U': options |= PCRE_UNGREEDY; break;        case 'U': options |= PCRE_UNGREEDY; break;
1226        case 'X': options |= PCRE_EXTRA; break;        case 'X': options |= PCRE_EXTRA; break;
1227          case 'Z': debug_lengths = 0; break;
1228        case '8': options |= PCRE_UTF8; use_utf8 = 1; break;        case '8': options |= PCRE_UTF8; use_utf8 = 1; break;
1229        case '?': options |= PCRE_NO_UTF8_CHECK; break;        case '?': options |= PCRE_NO_UTF8_CHECK; break;
1230    
1231        case 'L':        case 'L':
1232        ppp = pp;        ppp = pp;
1233        /* The '\r' test here is so that it works on Windows */        /* The '\r' test here is so that it works on Windows. */
1234        while (*ppp != '\n' && *ppp != '\r' && *ppp != ' ') ppp++;        /* The '0' test is just in case this is an unterminated line. */
1235          while (*ppp != 0 && *ppp != '\n' && *ppp != '\r' && *ppp != ' ') ppp++;
1236        *ppp = 0;        *ppp = 0;
1237        if (setlocale(LC_CTYPE, (const char *)pp) == NULL)        if (setlocale(LC_CTYPE, (const char *)pp) == NULL)
1238          {          {
1239          fprintf(outfile, "** Failed to set locale \"%s\"\n", pp);          fprintf(outfile, "** Failed to set locale \"%s\"\n", pp);
1240          goto SKIP_DATA;          goto SKIP_DATA;
1241          }          }
1242          locale_set = 1;
1243        tables = pcre_maketables();        tables = pcre_maketables();
1244        pp = ppp;        pp = ppp;
1245        break;        break;
# Line 1063  while (!done) Line 1253  while (!done)
1253    
1254        case '<':        case '<':
1255          {          {
1256          int x = check_newline(pp, outfile);          if (strncmp((char *)pp, "JS>", 3) == 0)
1257          if (x == 0) goto SKIP_DATA;            {
1258          options |= x;            options |= PCRE_JAVASCRIPT_COMPAT;
1259          while (*pp++ != '>');            pp += 3;
1260              }
1261            else
1262              {
1263              int x = check_newline(pp, outfile);
1264              if (x == 0) goto SKIP_DATA;
1265              options |= x;
1266              while (*pp++ != '>');
1267              }
1268          }          }
1269        break;        break;
1270    
# Line 1116  while (!done) Line 1314  while (!done)
1314  #endif  /* !defined NOPOSIX */  #endif  /* !defined NOPOSIX */
1315    
1316      {      {
1317      if (timeit)      if (timeit > 0)
1318        {        {
1319        register int i;        register int i;
1320        clock_t time_taken;        clock_t time_taken;
1321        clock_t start_time = clock();        clock_t start_time = clock();
1322        for (i = 0; i < LOOPREPEAT; i++)        for (i = 0; i < timeit; i++)
1323          {          {
1324          re = pcre_compile((char *)p, options, &error, &erroroffset, tables);          re = pcre_compile((char *)p, options, &error, &erroroffset, tables);
1325          if (re != NULL) free(re);          if (re != NULL) free(re);
1326          }          }
1327        time_taken = clock() - start_time;        time_taken = clock() - start_time;
1328        fprintf(outfile, "Compile time %.3f milliseconds\n",        fprintf(outfile, "Compile time %.4f milliseconds\n",
1329          (((double)time_taken * 1000.0) / (double)LOOPREPEAT) /          (((double)time_taken * 1000.0) / (double)timeit) /
1330            (double)CLOCKS_PER_SEC);            (double)CLOCKS_PER_SEC);
1331        }        }
1332    
# Line 1145  while (!done) Line 1343  while (!done)
1343          {          {
1344          for (;;)          for (;;)
1345            {            {
1346            if (extend_inputline(infile, buffer) == NULL)            if (extend_inputline(infile, buffer, NULL) == NULL)
1347              {              {
1348              done = 1;              done = 1;
1349              goto CONTINUE;              goto CONTINUE;
# Line 1180  while (!done) Line 1378  while (!done)
1378    
1379      if (do_study)      if (do_study)
1380        {        {
1381        if (timeit)        if (timeit > 0)
1382          {          {
1383          register int i;          register int i;
1384          clock_t time_taken;          clock_t time_taken;
1385          clock_t start_time = clock();          clock_t start_time = clock();
1386          for (i = 0; i < LOOPREPEAT; i++)          for (i = 0; i < timeit; i++)
1387            extra = pcre_study(re, study_options, &error);            extra = pcre_study(re, study_options, &error);
1388          time_taken = clock() - start_time;          time_taken = clock() - start_time;
1389          if (extra != NULL) free(extra);          if (extra != NULL) free(extra);
1390          fprintf(outfile, "  Study time %.3f milliseconds\n",          fprintf(outfile, "  Study time %.4f milliseconds\n",
1391            (((double)time_taken * 1000.0) / (double)LOOPREPEAT) /            (((double)time_taken * 1000.0) / (double)timeit) /
1392              (double)CLOCKS_PER_SEC);              (double)CLOCKS_PER_SEC);
1393          }          }
1394        extra = pcre_study(re, study_options, &error);        extra = pcre_study(re, study_options, &error);
# Line 1208  while (!done) Line 1406  while (!done)
1406      if (do_flip)      if (do_flip)
1407        {        {
1408        real_pcre *rre = (real_pcre *)re;        real_pcre *rre = (real_pcre *)re;
1409        rre->magic_number = byteflip(rre->magic_number, sizeof(rre->magic_number));        rre->magic_number =
1410            byteflip(rre->magic_number, sizeof(rre->magic_number));
1411        rre->size = byteflip(rre->size, sizeof(rre->size));        rre->size = byteflip(rre->size, sizeof(rre->size));
1412        rre->options = byteflip(rre->options, sizeof(rre->options));        rre->options = byteflip(rre->options, sizeof(rre->options));
1413        rre->top_bracket = byteflip(rre->top_bracket, sizeof(rre->top_bracket));        rre->flags = (pcre_uint16)byteflip(rre->flags, sizeof(rre->flags));
1414        rre->top_backref = byteflip(rre->top_backref, sizeof(rre->top_backref));        rre->top_bracket =
1415        rre->first_byte = byteflip(rre->first_byte, sizeof(rre->first_byte));          (pcre_uint16)byteflip(rre->top_bracket, sizeof(rre->top_bracket));
1416        rre->req_byte = byteflip(rre->req_byte, sizeof(rre->req_byte));        rre->top_backref =
1417        rre->name_table_offset = byteflip(rre->name_table_offset,          (pcre_uint16)byteflip(rre->top_backref, sizeof(rre->top_backref));
1418          rre->first_byte =
1419            (pcre_uint16)byteflip(rre->first_byte, sizeof(rre->first_byte));
1420          rre->req_byte =
1421            (pcre_uint16)byteflip(rre->req_byte, sizeof(rre->req_byte));
1422          rre->name_table_offset = (pcre_uint16)byteflip(rre->name_table_offset,
1423          sizeof(rre->name_table_offset));          sizeof(rre->name_table_offset));
1424        rre->name_entry_size = byteflip(rre->name_entry_size,        rre->name_entry_size = (pcre_uint16)byteflip(rre->name_entry_size,
1425          sizeof(rre->name_entry_size));          sizeof(rre->name_entry_size));
1426        rre->name_count = byteflip(rre->name_count, sizeof(rre->name_count));        rre->name_count = (pcre_uint16)byteflip(rre->name_count,
1427            sizeof(rre->name_count));
1428    
1429        if (extra != NULL)        if (extra != NULL)
1430          {          {
# Line 1233  while (!done) Line 1438  while (!done)
1438    
1439      SHOW_INFO:      SHOW_INFO:
1440    
1441        if (do_debug)
1442          {
1443          fprintf(outfile, "------------------------------------------------------------------\n");
1444          pcre_printint(re, outfile, debug_lengths);
1445          }
1446    
1447      if (do_showinfo)      if (do_showinfo)
1448        {        {
1449        unsigned long int get_options, all_options;        unsigned long int get_options, all_options;
1450  #if !defined NOINFOCHECK  #if !defined NOINFOCHECK
1451        int old_first_char, old_options, old_count;        int old_first_char, old_options, old_count;
1452  #endif  #endif
1453        int count, backrefmax, first_char, need_char;        int count, backrefmax, first_char, need_char, okpartial, jchanged,
1454            hascrorlf;
1455        int nameentrysize, namecount;        int nameentrysize, namecount;
1456        const uschar *nametable;        const uschar *nametable;
1457    
       if (do_debug)  
         {  
         fprintf(outfile, "------------------------------------------------------------------\n");  
         pcre_printint(re, outfile);  
         }  
   
1458        new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options);        new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options);
1459        new_info(re, NULL, PCRE_INFO_SIZE, &size);        new_info(re, NULL, PCRE_INFO_SIZE, &size);
1460        new_info(re, NULL, PCRE_INFO_CAPTURECOUNT, &count);        new_info(re, NULL, PCRE_INFO_CAPTURECOUNT, &count);
# Line 1258  while (!done) Line 1464  while (!done)
1464        new_info(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &nameentrysize);        new_info(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &nameentrysize);
1465        new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount);        new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount);
1466        new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable);        new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable);
1467          new_info(re, NULL, PCRE_INFO_OKPARTIAL, &okpartial);
1468          new_info(re, NULL, PCRE_INFO_JCHANGED, &jchanged);
1469          new_info(re, NULL, PCRE_INFO_HASCRORLF, &hascrorlf);
1470    
1471  #if !defined NOINFOCHECK  #if !defined NOINFOCHECK
1472        old_count = pcre_info(re, &old_options, &old_first_char);        old_count = pcre_info(re, &old_options, &old_first_char);
# Line 1299  while (!done) Line 1508  while (!done)
1508            }            }
1509          }          }
1510    
1511        /* The NOPARTIAL bit is a private bit in the options, so we have        if (!okpartial) fprintf(outfile, "Partial matching not supported\n");
1512        to fish it out via out back door */        if (hascrorlf) fprintf(outfile, "Contains explicit CR or LF match\n");
1513    
1514        all_options = ((real_pcre *)re)->options;        all_options = ((real_pcre *)re)->options;
1515        if (do_flip)        if (do_flip) all_options = byteflip(all_options, sizeof(all_options));
         {  
         all_options = byteflip(all_options, sizeof(all_options));  
          }  
   
       if ((all_options & PCRE_NOPARTIAL) != 0)  
         fprintf(outfile, "Partial matching not supported\n");  
1516    
1517        if (get_options == 0) fprintf(outfile, "No options\n");        if (get_options == 0) fprintf(outfile, "No options\n");
1518          else fprintf(outfile, "Options:%s%s%s%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%s%s%s\n",
1519            ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "",            ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "",
1520            ((get_options & PCRE_CASELESS) != 0)? " caseless" : "",            ((get_options & PCRE_CASELESS) != 0)? " caseless" : "",
1521            ((get_options & PCRE_EXTENDED) != 0)? " extended" : "",            ((get_options & PCRE_EXTENDED) != 0)? " extended" : "",
1522            ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "",            ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "",
1523            ((get_options & PCRE_FIRSTLINE) != 0)? " firstline" : "",            ((get_options & PCRE_FIRSTLINE) != 0)? " firstline" : "",
1524            ((get_options & PCRE_DOTALL) != 0)? " dotall" : "",            ((get_options & PCRE_DOTALL) != 0)? " dotall" : "",
1525              ((get_options & PCRE_BSR_ANYCRLF) != 0)? " bsr_anycrlf" : "",
1526              ((get_options & PCRE_BSR_UNICODE) != 0)? " bsr_unicode" : "",
1527            ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",            ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",
1528            ((get_options & PCRE_EXTRA) != 0)? " extra" : "",            ((get_options & PCRE_EXTRA) != 0)? " extra" : "",
1529            ((get_options & PCRE_UNGREEDY) != 0)? " ungreedy" : "",            ((get_options & PCRE_UNGREEDY) != 0)? " ungreedy" : "",
# Line 1327  while (!done) Line 1532  while (!done)
1532            ((get_options & PCRE_NO_UTF8_CHECK) != 0)? " no_utf8_check" : "",            ((get_options & PCRE_NO_UTF8_CHECK) != 0)? " no_utf8_check" : "",
1533            ((get_options & PCRE_DUPNAMES) != 0)? " dupnames" : "");            ((get_options & PCRE_DUPNAMES) != 0)? " dupnames" : "");
1534    
1535        switch (get_options & PCRE_NEWLINE_CRLF)        if (jchanged) fprintf(outfile, "Duplicate name status changes\n");
1536    
1537          switch (get_options & PCRE_NEWLINE_BITS)
1538          {          {
1539          case PCRE_NEWLINE_CR:          case PCRE_NEWLINE_CR:
1540          fprintf(outfile, "Forced newline sequence: CR\n");          fprintf(outfile, "Forced newline sequence: CR\n");
# Line 1341  while (!done) Line 1548  while (!done)
1548          fprintf(outfile, "Forced newline sequence: CRLF\n");          fprintf(outfile, "Forced newline sequence: CRLF\n");
1549          break;          break;
1550    
1551            case PCRE_NEWLINE_ANYCRLF:
1552            fprintf(outfile, "Forced newline sequence: ANYCRLF\n");
1553            break;
1554    
1555            case PCRE_NEWLINE_ANY:
1556            fprintf(outfile, "Forced newline sequence: ANY\n");
1557            break;
1558    
1559          default:          default:
1560          break;          break;
1561          }          }
# Line 1358  while (!done) Line 1573  while (!done)
1573          int ch = first_char & 255;          int ch = first_char & 255;
1574          const char *caseless = ((first_char & REQ_CASELESS) == 0)?          const char *caseless = ((first_char & REQ_CASELESS) == 0)?
1575            "" : " (caseless)";            "" : " (caseless)";
1576          if (isprint(ch))          if (PRINTHEX(ch))
1577            fprintf(outfile, "First char = \'%c\'%s\n", ch, caseless);            fprintf(outfile, "First char = \'%c\'%s\n", ch, caseless);
1578          else          else
1579            fprintf(outfile, "First char = %d%s\n", ch, caseless);            fprintf(outfile, "First char = %d%s\n", ch, caseless);
# Line 1373  while (!done) Line 1588  while (!done)
1588          int ch = need_char & 255;          int ch = need_char & 255;
1589          const char *caseless = ((need_char & REQ_CASELESS) == 0)?          const char *caseless = ((need_char & REQ_CASELESS) == 0)?
1590            "" : " (caseless)";            "" : " (caseless)";
1591          if (isprint(ch))          if (PRINTHEX(ch))
1592            fprintf(outfile, "Need char = \'%c\'%s\n", ch, caseless);            fprintf(outfile, "Need char = \'%c\'%s\n", ch, caseless);
1593          else          else
1594            fprintf(outfile, "Need char = %d%s\n", ch, caseless);            fprintf(outfile, "Need char = %d%s\n", ch, caseless);
# Line 1409  while (!done) Line 1624  while (!done)
1624                    fprintf(outfile, "\n  ");                    fprintf(outfile, "\n  ");
1625                    c = 2;                    c = 2;
1626                    }                    }
1627                  if (isprint(i) && i != ' ')                  if (PRINTHEX(i) && i != ' ')
1628                    {                    {
1629                    fprintf(outfile, "%c ", i);                    fprintf(outfile, "%c ", i);
1630                    c += 2;                    c += 2;
# Line 1441  while (!done) Line 1656  while (!done)
1656        else        else
1657          {          {
1658          uschar sbuf[8];          uschar sbuf[8];
1659          sbuf[0] = (true_size >> 24)  & 255;          sbuf[0] = (uschar)((true_size >> 24) & 255);
1660          sbuf[1] = (true_size >> 16)  & 255;          sbuf[1] = (uschar)((true_size >> 16) & 255);
1661          sbuf[2] = (true_size >>  8)  & 255;          sbuf[2] = (uschar)((true_size >>  8) & 255);
1662          sbuf[3] = (true_size)  & 255;          sbuf[3] = (uschar)((true_size) & 255);
1663    
1664          sbuf[4] = (true_study_size >> 24)  & 255;          sbuf[4] = (uschar)((true_study_size >> 24) & 255);
1665          sbuf[5] = (true_study_size >> 16)  & 255;          sbuf[5] = (uschar)((true_study_size >> 16) & 255);
1666          sbuf[6] = (true_study_size >>  8)  & 255;          sbuf[6] = (uschar)((true_study_size >>  8) & 255);
1667          sbuf[7] = (true_study_size)  & 255;          sbuf[7] = (uschar)((true_study_size) & 255);
1668    
1669          if (fwrite(sbuf, 1, 8, f) < 8 ||          if (fwrite(sbuf, 1, 8, f) < 8 ||
1670              fwrite(re, 1, true_size, f) < true_size)              fwrite(re, 1, true_size, f) < true_size)
# Line 1468  while (!done) Line 1683  while (!done)
1683                  strerror(errno));                  strerror(errno));
1684                }                }
1685              else fprintf(outfile, "Study data written to %s\n", to_file);              else fprintf(outfile, "Study data written to %s\n", to_file);
1686    
1687              }              }
1688            }            }
1689          fclose(f);          fclose(f);
# Line 1485  while (!done) Line 1701  while (!done)
1701    for (;;)    for (;;)
1702      {      {
1703      uschar *q;      uschar *q;
1704      uschar *bptr = dbuffer;      uschar *bptr;
1705      int *use_offsets = offsets;      int *use_offsets = offsets;
1706      int use_size_offsets = size_offsets;      int use_size_offsets = size_offsets;
1707      int callout_data = 0;      int callout_data = 0;
# Line 1522  while (!done) Line 1738  while (!done)
1738      len = 0;      len = 0;
1739      for (;;)      for (;;)
1740        {        {
1741        if (infile == stdin) printf("data> ");        if (extend_inputline(infile, buffer + len, "data> ") == NULL)
       if (extend_inputline(infile, buffer + len) == NULL)  
1742          {          {
1743          if (len > 0) break;          if (len > 0) break;
1744          done = 1;          done = 1;
# Line 1541  while (!done) Line 1756  while (!done)
1756      p = buffer;      p = buffer;
1757      while (isspace(*p)) p++;      while (isspace(*p)) p++;
1758    
1759      q = dbuffer;      bptr = q = dbuffer;
1760      while ((c = *p++) != 0)      while ((c = *p++) != 0)
1761        {        {
1762        int i = 0;        int i = 0;
# Line 1591  while (!done) Line 1806  while (!done)
1806              {              {
1807              unsigned char buff8[8];              unsigned char buff8[8];
1808              int ii, utn;              int ii, utn;
1809              utn = ord2utf8(c, buff8);              if (use_utf8)
1810              for (ii = 0; ii < utn - 1; ii++) *q++ = buff8[ii];                {
1811              c = buff8[ii];   /* Last byte */                utn = ord2utf8(c, buff8);
1812                  for (ii = 0; ii < utn - 1; ii++) *q++ = buff8[ii];
1813                  c = buff8[ii];   /* Last byte */
1814                  }
1815                else
1816                 {
1817                 if (c > 255)
1818                   fprintf(outfile, "** Character \\x{%x} is greater than 255 and "
1819                     "UTF-8 mode is not enabled.\n"
1820                     "** Truncation will probably give the wrong result.\n", c);
1821                 }
1822              p = pt + 1;              p = pt + 1;
1823              break;              break;
1824              }              }
# Line 1736  while (!done) Line 1961  while (!done)
1961            if (offsets == NULL)            if (offsets == NULL)
1962              {              {
1963              printf("** Failed to get %d bytes of memory for offsets vector\n",              printf("** Failed to get %d bytes of memory for offsets vector\n",
1964                size_offsets_max * sizeof(int));                (int)(size_offsets_max * sizeof(int)));
1965              yield = 1;              yield = 1;
1966              goto EXIT;              goto EXIT;
1967              }              }
# Line 1802  while (!done) Line 2027  while (!done)
2027        }        }
2028      *q = 0;      *q = 0;
2029      len = q - dbuffer;      len = q - dbuffer;
2030    
2031        /* Move the data to the end of the buffer so that a read over the end of
2032        the buffer will be seen by valgrind, even if it doesn't cause a crash. */
2033    
2034        memmove(bptr + buffer_size - len, bptr, len);
2035        bptr += buffer_size - len;
2036    
2037      if ((all_use_dfa || use_dfa) && find_match_limit)      if ((all_use_dfa || use_dfa) && find_match_limit)
2038        {        {
# Line 1866  while (!done) Line 2097  while (!done)
2097    
2098      for (;; gmatched++)    /* Loop for /g or /G */      for (;; gmatched++)    /* Loop for /g or /G */
2099        {        {
2100        if (timeit)        if (timeitm > 0)
2101          {          {
2102          register int i;          register int i;
2103          clock_t time_taken;          clock_t time_taken;
# Line 1876  while (!done) Line 2107  while (!done)
2107          if (all_use_dfa || use_dfa)          if (all_use_dfa || use_dfa)
2108            {            {
2109            int workspace[1000];            int workspace[1000];
2110            for (i = 0; i < LOOPREPEAT; i++)            for (i = 0; i < timeitm; i++)
2111              count = pcre_dfa_exec(re, NULL, (char *)bptr, len, start_offset,              count = pcre_dfa_exec(re, NULL, (char *)bptr, len, start_offset,
2112                options | g_notempty, use_offsets, use_size_offsets, workspace,                options | g_notempty, use_offsets, use_size_offsets, workspace,
2113                sizeof(workspace)/sizeof(int));                sizeof(workspace)/sizeof(int));
# Line 1884  while (!done) Line 2115  while (!done)
2115          else          else
2116  #endif  #endif
2117    
2118          for (i = 0; i < LOOPREPEAT; i++)          for (i = 0; i < timeitm; i++)
2119            count = pcre_exec(re, extra, (char *)bptr, len,            count = pcre_exec(re, extra, (char *)bptr, len,
2120              start_offset, options | g_notempty, use_offsets, use_size_offsets);              start_offset, options | g_notempty, use_offsets, use_size_offsets);
2121    
2122          time_taken = clock() - start_time;          time_taken = clock() - start_time;
2123          fprintf(outfile, "Execute time %.3f milliseconds\n",          fprintf(outfile, "Execute time %.4f milliseconds\n",
2124            (((double)time_taken * 1000.0) / (double)LOOPREPEAT) /            (((double)time_taken * 1000.0) / (double)timeitm) /
2125              (double)CLOCKS_PER_SEC);              (double)CLOCKS_PER_SEC);
2126          }          }
2127    
# Line 1966  while (!done) Line 2197  while (!done)
2197    
2198        if (count >= 0)        if (count >= 0)
2199          {          {
2200          int i;          int i, maxcount;
2201    
2202    #if !defined NODFA
2203            if (all_use_dfa || use_dfa) maxcount = use_size_offsets/2; else
2204    #endif
2205              maxcount = use_size_offsets/3;
2206    
2207            /* This is a check against a lunatic return value. */
2208    
2209            if (count > maxcount)
2210              {
2211              fprintf(outfile,
2212                "** PCRE error: returned count %d is too big for offset size %d\n",
2213                count, use_size_offsets);
2214              count = use_size_offsets/3;
2215              if (do_g || do_G)
2216                {
2217                fprintf(outfile, "** /%c loop abandoned\n", do_g? 'g' : 'G');
2218                do_g = do_G = FALSE;        /* Break g/G loop */
2219                }
2220              }
2221    
2222          for (i = 0; i < count * 2; i += 2)          for (i = 0; i < count * 2; i += 2)
2223            {            {
2224            if (use_offsets[i] < 0)            if (use_offsets[i] < 0)
# Line 2084  while (!done) Line 2336  while (!done)
2336          }          }
2337    
2338        /* Failed to match. If this is a /g or /G loop and we previously set        /* Failed to match. If this is a /g or /G loop and we previously set
2339        g_notempty after a null match, this is not necessarily the end.        g_notempty after a null match, this is not necessarily the end. We want
2340        We want to advance the start offset, and continue. In the case of UTF-8        to advance the start offset, and continue. We won't be at the end of the
2341        matching, the advance must be one character, not one byte. Fudge the        string - that was checked before setting g_notempty.
2342        offset values to achieve this. We won't be at the end of the string -  
2343        that was checked before setting g_notempty. */        Complication arises in the case when the newline option is "any" or
2344          "anycrlf". If the previous match was at the end of a line terminated by
2345          CRLF, an advance of one character just passes the \r, whereas we should
2346          prefer the longer newline sequence, as does the code in pcre_exec().
2347          Fudge the offset value to achieve this.
2348    
2349          Otherwise, in the case of UTF-8 matching, the advance must be one
2350          character, not one byte. */
2351    
2352        else        else
2353          {          {
2354          if (g_notempty != 0)          if (g_notempty != 0)
2355            {            {
2356            int onechar = 1;            int onechar = 1;
2357              unsigned int obits = ((real_pcre *)re)->options;
2358            use_offsets[0] = start_offset;            use_offsets[0] = start_offset;
2359            if (use_utf8)            if ((obits & PCRE_NEWLINE_BITS) == 0)
2360                {
2361                int d;
2362                (void)pcre_config(PCRE_CONFIG_NEWLINE, &d);
2363                obits = (d == '\r')? PCRE_NEWLINE_CR :
2364                        (d == '\n')? PCRE_NEWLINE_LF :
2365                        (d == ('\r'<<8 | '\n'))? PCRE_NEWLINE_CRLF :
2366                        (d == -2)? PCRE_NEWLINE_ANYCRLF :
2367                        (d == -1)? PCRE_NEWLINE_ANY : 0;
2368                }
2369              if (((obits & PCRE_NEWLINE_BITS) == PCRE_NEWLINE_ANY ||
2370                   (obits & PCRE_NEWLINE_BITS) == PCRE_NEWLINE_ANYCRLF)
2371                  &&
2372                  start_offset < len - 1 &&
2373                  bptr[start_offset] == '\r' &&
2374                  bptr[start_offset+1] == '\n')
2375                onechar++;
2376              else if (use_utf8)
2377              {              {
2378              while (start_offset + onechar < len)              while (start_offset + onechar < len)
2379                {                {
# Line 2131  while (!done) Line 2408  while (!done)
2408        character. */        character. */
2409    
2410        g_notempty = 0;        g_notempty = 0;
2411    
2412        if (use_offsets[0] == use_offsets[1])        if (use_offsets[0] == use_offsets[1])
2413          {          {
2414          if (use_offsets[0] == len) break;          if (use_offsets[0] == len) break;
# Line 2165  while (!done) Line 2443  while (!done)
2443      {      {
2444      new_free((void *)tables);      new_free((void *)tables);
2445      setlocale(LC_CTYPE, "C");      setlocale(LC_CTYPE, "C");
2446        locale_set = 0;
2447      }      }
2448    }    }
2449    

Legend:
Removed from v.91  
changed lines
  Added in v.361

  ViewVC Help
Powered by ViewVC 1.1.5