# Diff of /code/trunk/pcre_dfa_exec.c

revision 579 by ph10, Wed Nov 24 17:39:25 2010 UTC revision 1100 by chpe, Tue Oct 16 15:56:26 2012 UTC
# Line 7  and semantics are as close as possible t Line 7  and semantics are as close as possible t
7  below for why this module is different).  below for why this module is different).
8
9                         Written by Philip Hazel                         Written by Philip Hazel
10             Copyright (c) 1997-2010 University of Cambridge             Copyright (c) 1997-2012 University of Cambridge
11
12  -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
13  Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
# Line 38  POSSIBILITY OF SUCH DAMAGE. Line 38  POSSIBILITY OF SUCH DAMAGE.
38  -----------------------------------------------------------------------------  -----------------------------------------------------------------------------
39  */  */
40

41  /* This module contains the external function pcre_dfa_exec(), which is an  /* This module contains the external function pcre_dfa_exec(), which is an
42  alternative matching function that uses a sort of DFA algorithm (not a true  alternative matching function that uses a sort of DFA algorithm (not a true
43  FSM). This is NOT Perl- compatible, but it has advantages in certain  FSM). This is NOT Perl-compatible, but it has advantages in certain
44  applications. */  applications. */
45
46
# Line 113  small value. Non-zero values in the tabl Line 112  small value. Non-zero values in the tabl
112  the character is to be found. ***NOTE*** If the start of this table is  the character is to be found. ***NOTE*** If the start of this table is
113  modified, the three tables that follow must also be modified. */  modified, the three tables that follow must also be modified. */
114
115  static const uschar coptable[] = {  static const pcre_uint8 coptable[] = {
116    0,                             /* End                                    */    0,                             /* End                                    */
117    0, 0, 0, 0, 0,                 /* \A, \G, \K, \B, \b                     */    0, 0, 0, 0, 0,                 /* \A, \G, \K, \B, \b                     */
118    0, 0, 0, 0, 0, 0,              /* \D, \d, \S, \s, \W, \w                 */    0, 0, 0, 0, 0, 0,              /* \D, \d, \S, \s, \W, \w                 */
# Line 121  static const uschar coptable[] = { Line 120  static const uschar coptable[] = {
120    0, 0,                          /* \P, \p                                 */    0, 0,                          /* \P, \p                                 */
121    0, 0, 0, 0, 0,                 /* \R, \H, \h, \V, \v                     */    0, 0, 0, 0, 0,                 /* \R, \H, \h, \V, \v                     */
122    0,                             /* \X                                     */    0,                             /* \X                                     */
123    0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, \$                      */    0, 0, 0, 0, 0, 0,              /* \Z, \z, ^, ^M, \$, \$M                   */
124    1,                             /* Char                                   */    1,                             /* Char                                   */
125    1,                             /* Charnc                                 */    1,                             /* Chari                                  */
126    1,                             /* not                                    */    1,                             /* not                                    */
127      1,                             /* noti                                   */
128    /* Positive single-char repeats                                          */    /* Positive single-char repeats                                          */
129    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
130    3, 3, 3,                       /* upto, minupto, exact                   */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* upto, minupto                          */
131    1, 1, 1, 3,                    /* *+, ++, ?+, upto+                      */    1+IMM2_SIZE,                   /* exact                                  */
132      1, 1, 1, 1+IMM2_SIZE,          /* *+, ++, ?+, upto+                      */
133      1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */
134      1+IMM2_SIZE, 1+IMM2_SIZE,      /* upto I, minupto I                      */
135      1+IMM2_SIZE,                   /* exact I                                */
136      1, 1, 1, 1+IMM2_SIZE,          /* *+I, ++I, ?+I, upto+I                  */
137    /* Negative single-char repeats - only for chars < 256                   */    /* Negative single-char repeats - only for chars < 256                   */
138    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
139    3, 3, 3,                       /* NOT upto, minupto, exact               */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* NOT upto, minupto                      */
140    1, 1, 1, 3,                    /* NOT *+, ++, ?+, updo+                  */    1+IMM2_SIZE,                   /* NOT exact                              */
141      1, 1, 1, 1+IMM2_SIZE,          /* NOT *+, ++, ?+, upto+                  */
142      1, 1, 1, 1, 1, 1,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */
143      1+IMM2_SIZE, 1+IMM2_SIZE,      /* NOT upto I, minupto I                  */
144      1+IMM2_SIZE,                   /* NOT exact I                            */
145      1, 1, 1, 1+IMM2_SIZE,          /* NOT *+I, ++I, ?+I, upto+I              */
146    /* Positive type repeats                                                 */    /* Positive type repeats                                                 */
147    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
148    3, 3, 3,                       /* Type upto, minupto, exact              */    1+IMM2_SIZE, 1+IMM2_SIZE,      /* Type upto, minupto                     */
149    1, 1, 1, 3,                    /* Type *+, ++, ?+, upto+                 */    1+IMM2_SIZE,                   /* Type exact                             */
150      1, 1, 1, 1+IMM2_SIZE,          /* Type *+, ++, ?+, upto+                 */
151    /* Character class & ref repeats                                         */    /* Character class & ref repeats                                         */
152    0, 0, 0, 0, 0, 0,              /* *, *?, +, +?, ?, ??                    */    0, 0, 0, 0, 0, 0,              /* *, *?, +, +?, ?, ??                    */
153    0, 0,                          /* CRRANGE, CRMINRANGE                    */    0, 0,                          /* CRRANGE, CRMINRANGE                    */
# Line 144  static const uschar coptable[] = { Line 155  static const uschar coptable[] = {
155    0,                             /* NCLASS                                 */    0,                             /* NCLASS                                 */
156    0,                             /* XCLASS - variable length               */    0,                             /* XCLASS - variable length               */
157    0,                             /* REF                                    */    0,                             /* REF                                    */
158      0,                             /* REFI                                   */
159    0,                             /* RECURSE                                */    0,                             /* RECURSE                                */
160    0,                             /* CALLOUT                                */    0,                             /* CALLOUT                                */
161    0,                             /* Alt                                    */    0,                             /* Alt                                    */
162    0,                             /* Ket                                    */    0,                             /* Ket                                    */
163    0,                             /* KetRmax                                */    0,                             /* KetRmax                                */
164    0,                             /* KetRmin                                */    0,                             /* KetRmin                                */
165      0,                             /* KetRpos                                */
166      0,                             /* Reverse                                */
167    0,                             /* Assert                                 */    0,                             /* Assert                                 */
168    0,                             /* Assert not                             */    0,                             /* Assert not                             */
169    0,                             /* Assert behind                          */    0,                             /* Assert behind                          */
170    0,                             /* Assert behind not                      */    0,                             /* Assert behind not                      */
171    0,                             /* Reverse                                */    0, 0,                          /* ONCE, ONCE_NC                          */
172    0, 0, 0, 0,                    /* ONCE, BRA, CBRA, COND                  */    0, 0, 0, 0, 0,                 /* BRA, BRAPOS, CBRA, CBRAPOS, COND       */
173    0, 0, 0,                       /* SBRA, SCBRA, SCOND                     */    0, 0, 0, 0, 0,                 /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND  */
174    0, 0,                          /* CREF, NCREF                            */    0, 0,                          /* CREF, NCREF                            */
175    0, 0,                          /* RREF, NRREF                            */    0, 0,                          /* RREF, NRREF                            */
176    0,                             /* DEF                                    */    0,                             /* DEF                                    */
177    0, 0,                          /* BRAZERO, BRAMINZERO                    */    0, 0, 0,                       /* BRAZERO, BRAMINZERO, BRAPOSZERO        */
178    0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG,                */    0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG                 */
179    0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG,        */    0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG         */
180    0, 0, 0, 0, 0                  /* COMMIT, FAIL, ACCEPT, CLOSE, SKIPZERO  */    0, 0, 0, 0,                    /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT    */
181      0, 0                           /* CLOSE, SKIPZERO  */
182  };  };
183
184  /* This table identifies those opcodes that inspect a character. It is used to  /* This table identifies those opcodes that inspect a character. It is used to
# Line 171  remember the fact that a character could Line 186  remember the fact that a character could
186  the subject is reached. ***NOTE*** If the start of this table is modified, the  the subject is reached. ***NOTE*** If the start of this table is modified, the
187  two tables that follow must also be modified. */  two tables that follow must also be modified. */
188
189  static const uschar poptable[] = {  static const pcre_uint8 poptable[] = {
190    0,                             /* End                                    */    0,                             /* End                                    */
191    0, 0, 0, 1, 1,                 /* \A, \G, \K, \B, \b                     */    0, 0, 0, 1, 1,                 /* \A, \G, \K, \B, \b                     */
192    1, 1, 1, 1, 1, 1,              /* \D, \d, \S, \s, \W, \w                 */    1, 1, 1, 1, 1, 1,              /* \D, \d, \S, \s, \W, \w                 */
# Line 179  static const uschar poptable[] = { Line 194  static const uschar poptable[] = {
194    1, 1,                          /* \P, \p                                 */    1, 1,                          /* \P, \p                                 */
195    1, 1, 1, 1, 1,                 /* \R, \H, \h, \V, \v                     */    1, 1, 1, 1, 1,                 /* \R, \H, \h, \V, \v                     */
196    1,                             /* \X                                     */    1,                             /* \X                                     */
197    0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, \$                      */    0, 0, 0, 0, 0, 0,              /* \Z, \z, ^, ^M, \$, \$M                   */
198    1,                             /* Char                                   */    1,                             /* Char                                   */
199    1,                             /* Charnc                                 */    1,                             /* Chari                                  */
200    1,                             /* not                                    */    1,                             /* not                                    */
201      1,                             /* noti                                   */
202    /* Positive single-char repeats                                          */    /* Positive single-char repeats                                          */
203    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
204    1, 1, 1,                       /* upto, minupto, exact                   */    1, 1, 1,                       /* upto, minupto, exact                   */
205    1, 1, 1, 1,                    /* *+, ++, ?+, upto+                      */    1, 1, 1, 1,                    /* *+, ++, ?+, upto+                      */
206      1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */
207      1, 1, 1,                       /* upto I, minupto I, exact I             */
208      1, 1, 1, 1,                    /* *+I, ++I, ?+I, upto+I                  */
209    /* Negative single-char repeats - only for chars < 256                   */    /* Negative single-char repeats - only for chars < 256                   */
210    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
211    1, 1, 1,                       /* NOT upto, minupto, exact               */    1, 1, 1,                       /* NOT upto, minupto, exact               */
212    1, 1, 1, 1,                    /* NOT *+, ++, ?+, upto+                  */    1, 1, 1, 1,                    /* NOT *+, ++, ?+, upto+                  */
213      1, 1, 1, 1, 1, 1,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */
214      1, 1, 1,                       /* NOT upto I, minupto I, exact I         */
215      1, 1, 1, 1,                    /* NOT *+I, ++I, ?+I, upto+I              */
216    /* Positive type repeats                                                 */    /* Positive type repeats                                                 */
217    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
218    1, 1, 1,                       /* Type upto, minupto, exact              */    1, 1, 1,                       /* Type upto, minupto, exact              */
# Line 202  static const uschar poptable[] = { Line 224  static const uschar poptable[] = {
224    1,                             /* NCLASS                                 */    1,                             /* NCLASS                                 */
225    1,                             /* XCLASS - variable length               */    1,                             /* XCLASS - variable length               */
226    0,                             /* REF                                    */    0,                             /* REF                                    */
227      0,                             /* REFI                                   */
228    0,                             /* RECURSE                                */    0,                             /* RECURSE                                */
229    0,                             /* CALLOUT                                */    0,                             /* CALLOUT                                */
230    0,                             /* Alt                                    */    0,                             /* Alt                                    */
231    0,                             /* Ket                                    */    0,                             /* Ket                                    */
232    0,                             /* KetRmax                                */    0,                             /* KetRmax                                */
233    0,                             /* KetRmin                                */    0,                             /* KetRmin                                */
234      0,                             /* KetRpos                                */
235      0,                             /* Reverse                                */
236    0,                             /* Assert                                 */    0,                             /* Assert                                 */
237    0,                             /* Assert not                             */    0,                             /* Assert not                             */
238    0,                             /* Assert behind                          */    0,                             /* Assert behind                          */
239    0,                             /* Assert behind not                      */    0,                             /* Assert behind not                      */
240    0,                             /* Reverse                                */    0, 0,                          /* ONCE, ONCE_NC                          */
241    0, 0, 0, 0,                    /* ONCE, BRA, CBRA, COND                  */    0, 0, 0, 0, 0,                 /* BRA, BRAPOS, CBRA, CBRAPOS, COND       */
242    0, 0, 0,                       /* SBRA, SCBRA, SCOND                     */    0, 0, 0, 0, 0,                 /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND  */
243    0, 0,                          /* CREF, NCREF                            */    0, 0,                          /* CREF, NCREF                            */
244    0, 0,                          /* RREF, NRREF                            */    0, 0,                          /* RREF, NRREF                            */
245    0,                             /* DEF                                    */    0,                             /* DEF                                    */
246    0, 0,                          /* BRAZERO, BRAMINZERO                    */    0, 0, 0,                       /* BRAZERO, BRAMINZERO, BRAPOSZERO        */
247    0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG,                */    0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG                 */
248    0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG,        */    0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG         */
249    0, 0, 0, 0, 0                  /* COMMIT, FAIL, ACCEPT, CLOSE, SKIPZERO  */    0, 0, 0, 0,                    /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT    */
250      0, 0                           /* CLOSE, SKIPZERO                        */
251  };  };
252
253  /* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,  /* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,
254  and \w */  and \w */
255
256  static const uschar toptable1[] = {  static const pcre_uint8 toptable1[] = {
257    0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0,
258    ctype_digit, ctype_digit,    ctype_digit, ctype_digit,
259    ctype_space, ctype_space,    ctype_space, ctype_space,
# Line 235  static const uschar toptable1[] = { Line 261  static const uschar toptable1[] = {
261    0, 0                            /* OP_ANY, OP_ALLANY */    0, 0                            /* OP_ANY, OP_ALLANY */
262  };  };
263
264  static const uschar toptable2[] = {  static const pcre_uint8 toptable2[] = {
265    0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0,
266    ctype_digit, 0,    ctype_digit, 0,
267    ctype_space, 0,    ctype_space, 0,
# Line 252  these structures in, is a vector of ints Line 278  these structures in, is a vector of ints
278  typedef struct stateblock {  typedef struct stateblock {
279    int offset;                     /* Offset to opcode */    int offset;                     /* Offset to opcode */
280    int count;                      /* Count for repeats */    int count;                      /* Count for repeats */
int ims;                        /* ims flag bits */
281    int data;                       /* Some use extra data */    int data;                       /* Some use extra data */
282  } stateblock;  } stateblock;
283
284  #define INTS_PER_STATEBLOCK  (sizeof(stateblock)/sizeof(int))  #define INTS_PER_STATEBLOCK  (int)(sizeof(stateblock)/sizeof(int))
285
286
287  #ifdef PCRE_DEBUG  #ifdef PCRE_DEBUG
# Line 275  Returns:       nothing Line 300  Returns:       nothing
300  */  */
301
302  static void  static void
303  pchars(unsigned char *p, int length, FILE *f)  pchars(const pcre_uchar *p, int length, FILE *f)
304  {  {
305  int c;  pcre_uint32 c;
306  while (length-- > 0)  while (length-- > 0)
307    {    {
308    if (isprint(c = *(p++)))    if (isprint(c = *(p++)))
309      fprintf(f, "%c", c);      fprintf(f, "%c", c);
310    else    else
311      fprintf(f, "\\x%02x", c);      fprintf(f, "\\x{%02x}", c);
312    }    }
313  }  }
314  #endif  #endif
# Line 308  Arguments: Line 333  Arguments:
333    offsetcount       size of same    offsetcount       size of same
334    workspace         vector of workspace    workspace         vector of workspace
335    wscount           size of same    wscount           size of same
ims               the current ims flags
336    rlevel            function call recursion level    rlevel            function call recursion level
recursing         regex recursive call level
337
338  Returns:            > 0 => number of match offset pairs placed in offsets  Returns:            > 0 => number of match offset pairs placed in offsets
339                      = 0 => offsets overflowed; longest matches are present                      = 0 => offsets overflowed; longest matches are present
# Line 325  for the current character, one for the f Line 348  for the current character, one for the f
348      { \      { \
349      next_active_state->offset = (x); \      next_active_state->offset = (x); \
350      next_active_state->count  = (y); \      next_active_state->count  = (y); \
next_active_state->ims    = ims; \
351      next_active_state++; \      next_active_state++; \
352      DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \      DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
353      } \      } \
# Line 336  for the current character, one for the f Line 358  for the current character, one for the f
358      { \      { \
359      next_active_state->offset = (x); \      next_active_state->offset = (x); \
360      next_active_state->count  = (y); \      next_active_state->count  = (y); \
next_active_state->ims    = ims; \
361      next_active_state->data   = (z); \      next_active_state->data   = (z); \
362      next_active_state++; \      next_active_state++; \
363      DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \      DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \
# Line 348  for the current character, one for the f Line 369  for the current character, one for the f
369      { \      { \
370      next_new_state->offset = (x); \      next_new_state->offset = (x); \
371      next_new_state->count  = (y); \      next_new_state->count  = (y); \
next_new_state->ims    = ims; \
372      next_new_state++; \      next_new_state++; \
373      DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \      DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
374      } \      } \
# Line 359  for the current character, one for the f Line 379  for the current character, one for the f
379      { \      { \
380      next_new_state->offset = (x); \      next_new_state->offset = (x); \
381      next_new_state->count  = (y); \      next_new_state->count  = (y); \
next_new_state->ims    = ims; \
382      next_new_state->data   = (z); \      next_new_state->data   = (z); \
383      next_new_state++; \      next_new_state++; \
384      DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \      DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d) line %d\n", rlevel*2-2, SP, \
385          (x), (y), (z), __LINE__)); \
386      } \      } \
387    else return PCRE_ERROR_DFA_WSSIZE    else return PCRE_ERROR_DFA_WSSIZE
388
# Line 371  for the current character, one for the f Line 391  for the current character, one for the f
391  static int  static int
392  internal_dfa_exec(  internal_dfa_exec(
393    dfa_match_data *md,    dfa_match_data *md,
394    const uschar *this_start_code,    const pcre_uchar *this_start_code,
395    const uschar *current_subject,    const pcre_uchar *current_subject,
396    int start_offset,    int start_offset,
397    int *offsets,    int *offsets,
398    int offsetcount,    int offsetcount,
399    int *workspace,    int *workspace,
400    int wscount,    int wscount,
401    int ims,    int  rlevel)
int  rlevel,
int  recursing)
402  {  {
403  stateblock *active_states, *new_states, *temp_states;  stateblock *active_states, *new_states, *temp_states;
404  stateblock *next_active_state, *next_new_state;  stateblock *next_active_state, *next_new_state;
405
406  const uschar *ctypes, *lcc, *fcc;  const pcre_uint8 *ctypes, *lcc, *fcc;
407  const uschar *ptr;  const pcre_uchar *ptr;
408  const uschar *end_code, *first_op;  const pcre_uchar *end_code, *first_op;
409
410    dfa_recursion_info new_recursive;
411
412  int active_count, new_count, match_count;  int active_count, new_count, match_count;
413
414  /* Some fields in the md block are frequently referenced, so we load them into  /* Some fields in the md block are frequently referenced, so we load them into
415  independent variables in the hope that this will perform better. */  independent variables in the hope that this will perform better. */
416
417  const uschar *start_subject = md->start_subject;  const pcre_uchar *start_subject = md->start_subject;
418  const uschar *end_subject = md->end_subject;  const pcre_uchar *end_subject = md->end_subject;
419  const uschar *start_code = md->start_code;  const pcre_uchar *start_code = md->start_code;
420
421  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
422  BOOL utf8 = (md->poptions & PCRE_UTF8) != 0;  BOOL utf = (md->poptions & PCRE_UTF8) != 0;
423  #else  #else
424  BOOL utf8 = FALSE;  BOOL utf = FALSE;
425  #endif  #endif
426
427    BOOL reset_could_continue = FALSE;
428
429  rlevel++;  rlevel++;
430  offsetcount &= (-2);  offsetcount &= (-2);
431
# Line 412  wscount = (wscount - (wscount % (INTS_PE Line 434  wscount = (wscount - (wscount % (INTS_PE
434            (2 * INTS_PER_STATEBLOCK);            (2 * INTS_PER_STATEBLOCK);
435
436  DPRINTF(("\n%.*s---------------------\n"  DPRINTF(("\n%.*s---------------------\n"
437    "%.*sCall to internal_dfa_exec f=%d r=%d\n",    "%.*sCall to internal_dfa_exec f=%d\n",
438    rlevel*2-2, SP, rlevel*2-2, SP, rlevel, recursing));    rlevel*2-2, SP, rlevel*2-2, SP, rlevel));
439
440  ctypes = md->tables + ctypes_offset;  ctypes = md->tables + ctypes_offset;
441  lcc = md->tables + lcc_offset;  lcc = md->tables + lcc_offset;
# Line 426  next_new_state = new_states = active_sta Line 448  next_new_state = new_states = active_sta
448  new_count = 0;  new_count = 0;
449
450  first_op = this_start_code + 1 + LINK_SIZE +  first_op = this_start_code + 1 + LINK_SIZE +
451    ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA)? 2:0);    ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||
452        *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)
453        ? IMM2_SIZE:0);
454
455  /* The first thing in any (sub) pattern is a bracket of some sort. Push all  /* The first thing in any (sub) pattern is a bracket of some sort. Push all
456  the alternative states onto the list, and find out where the end is. This  the alternative states onto the list, and find out where the end is. This
# Line 454  if (*first_op == OP_REVERSE) Line 478  if (*first_op == OP_REVERSE)
478    /* If we can't go back the amount required for the longest lookbehind    /* If we can't go back the amount required for the longest lookbehind
479    pattern, go back as far as we can; some alternatives may still be viable. */    pattern, go back as far as we can; some alternatives may still be viable. */
480
481  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
482    /* In character mode we have to step back character by character */    /* In character mode we have to step back character by character */
483
484    if (utf8)    if (utf)
485      {      {
486      for (gone_back = 0; gone_back < max_back; gone_back++)      for (gone_back = 0; gone_back < max_back; gone_back++)
487        {        {
488        if (current_subject <= start_subject) break;        if (current_subject <= start_subject) break;
489        current_subject--;        current_subject--;
490        while (current_subject > start_subject &&        ACROSSCHAR(current_subject > start_subject, *current_subject, current_subject--);
(*current_subject & 0xc0) == 0x80)
current_subject--;
491        }        }
492      }      }
493    else    else
# Line 525  else Line 547  else
547    else    else
548      {      {
549      int length = 1 + LINK_SIZE +      int length = 1 + LINK_SIZE +
550        ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA)? 2:0);        ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||
551            *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)
552            ? IMM2_SIZE:0);
553      do      do
554        {        {
555        ADD_NEW((int)(end_code - start_code + length), 0);        ADD_NEW((int)(end_code - start_code + length), 0);
# Line 538  else Line 562  else
562
563  workspace[0] = 0;    /* Bit indicating which vector is current */  workspace[0] = 0;    /* Bit indicating which vector is current */
564
565  DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, end_code - start_code));  DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, (int)(end_code - start_code)));
566
567  /* Loop for scanning the subject */  /* Loop for scanning the subject */
568
# Line 547  for (;;) Line 571  for (;;)
571    {    {
572    int i, j;    int i, j;
573    int clen, dlen;    int clen, dlen;
574    unsigned int c, d;    pcre_uint32 c, d;
575    int forced_fail = 0;    int forced_fail = 0;
576    BOOL could_continue = FALSE;    BOOL partial_newline = FALSE;
577      BOOL could_continue = reset_could_continue;
578      reset_could_continue = FALSE;
579
580    /* Make the new state list into the active state list and empty the    /* Make the new state list into the active state list and empty the
581    new state list. */    new state list. */
# Line 565  for (;;) Line 591  for (;;)
591
592  #ifdef PCRE_DEBUG  #ifdef PCRE_DEBUG
593    printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP);    printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP);
594    pchars((uschar *)ptr, strlen((char *)ptr), stdout);    pchars(ptr, STRLEN_UC(ptr), stdout);
595    printf("\"\n");    printf("\"\n");
596
597    printf("%.*sActive states: ", rlevel*2-2, SP);    printf("%.*sActive states: ", rlevel*2-2, SP);
# Line 585  for (;;) Line 611  for (;;)
611
612    if (ptr < end_subject)    if (ptr < end_subject)
613      {      {
614      clen = 1;        /* Number of bytes in the character */      clen = 1;        /* Number of data items in the character */
615  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
616      if (utf8) { GETCHARLEN(c, ptr, clen); } else      GETCHARLENTEST(c, ptr, clen);
617  #endif  /* SUPPORT_UTF8 */  #else
618      c = *ptr;      c = *ptr;
619    #endif  /* SUPPORT_UTF */
620      }      }
621    else    else
622      {      {
# Line 605  for (;;) Line 632  for (;;)
632    for (i = 0; i < active_count; i++)    for (i = 0; i < active_count; i++)
633      {      {
634      stateblock *current_state = active_states + i;      stateblock *current_state = active_states + i;
635      const uschar *code;      BOOL caseless = FALSE;
636        const pcre_uchar *code;
637      int state_offset = current_state->offset;      int state_offset = current_state->offset;
638      int count, codevalue, rrc;      int count, codevalue, rrc;
639
# Line 616  for (;;) Line 644  for (;;)
644          else printf("0x%02x\n", c);          else printf("0x%02x\n", c);
645  #endif  #endif
646
/* This variable is referred to implicity in the ADD_xxx macros. */

ims = current_state->ims;

647      /* A negative offset is a special case meaning "hold off going to this      /* A negative offset is a special case meaning "hold off going to this
648      (negated) state until the number of characters in the data field have      (negated) state until the number of characters in the data field have
649      been skipped". */      been skipped". If the could_continue flag was passed over from a previous
650        state, arrange for it to passed on. */
651
652      if (state_offset < 0)      if (state_offset < 0)
653        {        {
# Line 631  for (;;) Line 656  for (;;)
656          DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP));          DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP));
658            current_state->data - 1);            current_state->data - 1);
659            if (could_continue) reset_could_continue = TRUE;
660          continue;          continue;
661          }          }
662        else        else
# Line 670  for (;;) Line 696  for (;;)
696      permitted.      permitted.
697
698      We also use this mechanism for opcodes such as OP_TYPEPLUS that take an      We also use this mechanism for opcodes such as OP_TYPEPLUS that take an
699      argument that is not a data character - but is always one byte long. We      argument that is not a data character - but is always one byte long because
700      have to take special action to deal with  \P, \p, \H, \h, \V, \v and \X in      the values are small. We have to take special action to deal with  \P, \p,
701      this case. To keep the other cases fast, convert these ones to new opcodes.      \H, \h, \V, \v and \X in this case. To keep the other cases fast, convert
702      */      these ones to new opcodes. */
703
704      if (coptable[codevalue] > 0)      if (coptable[codevalue] > 0)
705        {        {
706        dlen = 1;        dlen = 1;
707  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
708        if (utf8) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else        if (utf) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else
709  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
710        d = code[coptable[codevalue]];        d = code[coptable[codevalue]];
711        if (codevalue >= OP_TYPESTAR)        if (codevalue >= OP_TYPESTAR)
712          {          {
# Line 725  for (;;) Line 751  for (;;)
751
752  /* ========================================================================== */  /* ========================================================================== */
753        /* Reached a closing bracket. If not at the end of the pattern, carry        /* Reached a closing bracket. If not at the end of the pattern, carry
754        on with the next opcode. Otherwise, unless we have an empty string and        on with the next opcode. For repeating opcodes, also add the repeat
755          state. Note that KETRPOS will always be encountered at the end of the
756          subpattern, because the possessive subpattern repeats are always handled
757          using recursive calls. Thus, it never adds any new states.
758
759          At the end of the (sub)pattern, unless we have an empty string and
760        PCRE_NOTEMPTY is set, or PCRE_NOTEMPTY_ATSTART is set and we are at the        PCRE_NOTEMPTY is set, or PCRE_NOTEMPTY_ATSTART is set and we are at the
761        start of the subject, save the match data, shifting up all previous        start of the subject, save the match data, shifting up all previous
762        matches so we always have the longest first. */        matches so we always have the longest first. */
# Line 733  for (;;) Line 764  for (;;)
764        case OP_KET:        case OP_KET:
765        case OP_KETRMIN:        case OP_KETRMIN:
766        case OP_KETRMAX:        case OP_KETRMAX:
767          case OP_KETRPOS:
768        if (code != end_code)        if (code != end_code)
769          {          {
# Line 749  for (;;) Line 781  for (;;)
781                  current_subject > start_subject + md->start_offset)))                  current_subject > start_subject + md->start_offset)))
782            {            {
783            if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;            if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;
784              else if (match_count > 0 && ++match_count * 2 >= offsetcount)              else if (match_count > 0 && ++match_count * 2 > offsetcount)
785                match_count = 0;                match_count = 0;
786            count = ((match_count == 0)? offsetcount : match_count * 2) - 2;            count = ((match_count == 0)? offsetcount : match_count * 2) - 2;
787            if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));            if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));
# Line 758  for (;;) Line 790  for (;;)
790              offsets[0] = (int)(current_subject - start_subject);              offsets[0] = (int)(current_subject - start_subject);
791              offsets[1] = (int)(ptr - start_subject);              offsets[1] = (int)(ptr - start_subject);
792              DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,              DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,
793                offsets[1] - offsets[0], current_subject));                offsets[1] - offsets[0], (char *)current_subject));
794              }              }
795            if ((md->moptions & PCRE_DFA_SHORTEST) != 0)            if ((md->moptions & PCRE_DFA_SHORTEST) != 0)
796              {              {
# Line 795  for (;;) Line 827  for (;;)
827        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
828        case OP_CBRA:        case OP_CBRA:
829        case OP_SCBRA:        case OP_SCBRA:
831        code += GET(code, 1);        code += GET(code, 1);
832        while (*code == OP_ALT)        while (*code == OP_ALT)
833          {          {
# Line 822  for (;;) Line 854  for (;;)
854
855        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
856        case OP_CIRC:        case OP_CIRC:
857          if (ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0)
858            { ADD_ACTIVE(state_offset + 1, 0); }
859          break;
860
861          /*-----------------------------------------------------------------*/
862          case OP_CIRCM:
863        if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||        if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||
864            ((ims & PCRE_MULTILINE) != 0 &&            (ptr != end_subject && WAS_NEWLINE(ptr)))
ptr != end_subject &&
WAS_NEWLINE(ptr)))
865          { ADD_ACTIVE(state_offset + 1, 0); }          { ADD_ACTIVE(state_offset + 1, 0); }
866        break;        break;
867
# Line 840  for (;;) Line 876  for (;;)
876        break;        break;
877
878        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
case OP_OPT:
ims = code[1];
break;

/*-----------------------------------------------------------------*/
879        case OP_SOD:        case OP_SOD:
880        if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); }        if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); }
881        break;        break;
# Line 865  for (;;) Line 895  for (;;)
895        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
896        case OP_ANY:        case OP_ANY:
897        if (clen > 0 && !IS_NEWLINE(ptr))        if (clen > 0 && !IS_NEWLINE(ptr))
898          { ADD_NEW(state_offset + 1, 0); }          {
899            if (ptr + 1 >= md->end_subject &&
900                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
901                NLBLOCK->nltype == NLTYPE_FIXED &&
902                NLBLOCK->nllen == 2 &&
903                c == NLBLOCK->nl[0])
904              {
905              could_continue = partial_newline = TRUE;
906              }
907            else
908              {
910              }
911            }
912        break;        break;
913
914        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
# Line 890  for (;;) Line 933  for (;;)
933            could_continue = TRUE;            could_continue = TRUE;
934          else if (clen == 0 ||          else if (clen == 0 ||
935              ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&              ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&
936                 ((ims & PCRE_MULTILINE) != 0 || ptr == end_subject - md->nllen)                 (ptr == end_subject - md->nllen)
937              ))              ))
938            { ADD_ACTIVE(state_offset + 1, 0); }            { ADD_ACTIVE(state_offset + 1, 0); }
939            else if (ptr + 1 >= md->end_subject &&
940                     (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
941                     NLBLOCK->nltype == NLTYPE_FIXED &&
942                     NLBLOCK->nllen == 2 &&
943                     c == NLBLOCK->nl[0])
944              {
945              if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
946                {
947                reset_could_continue = TRUE;
948                ADD_NEW_DATA(-(state_offset + 1), 0, 1);
949                }
950              else could_continue = partial_newline = TRUE;
951              }
952            }
953          break;
954
955          /*-----------------------------------------------------------------*/
956          case OP_DOLLM:
957          if ((md->moptions & PCRE_NOTEOL) == 0)
958            {
959            if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
960              could_continue = TRUE;
961            else if (clen == 0 ||
962                ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))
963              { ADD_ACTIVE(state_offset + 1, 0); }
964            else if (ptr + 1 >= md->end_subject &&
965                     (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
966                     NLBLOCK->nltype == NLTYPE_FIXED &&
967                     NLBLOCK->nllen == 2 &&
968                     c == NLBLOCK->nl[0])
969              {
970              if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
971                {
972                reset_could_continue = TRUE;
973                ADD_NEW_DATA(-(state_offset + 1), 0, 1);
974                }
975              else could_continue = partial_newline = TRUE;
976              }
977          }          }
978        else if ((ims & PCRE_MULTILINE) != 0 && IS_NEWLINE(ptr))        else if (IS_NEWLINE(ptr))
979          { ADD_ACTIVE(state_offset + 1, 0); }          { ADD_ACTIVE(state_offset + 1, 0); }
980        break;        break;
981
# Line 925  for (;;) Line 1006  for (;;)
1006
1007          if (ptr > start_subject)          if (ptr > start_subject)
1008            {            {
1009            const uschar *temp = ptr - 1;            const pcre_uchar *temp = ptr - 1;
1010            if (temp < md->start_used_ptr) md->start_used_ptr = temp;            if (temp < md->start_used_ptr) md->start_used_ptr = temp;
1011  #ifdef SUPPORT_UTF8  #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
1012            if (utf8) BACKCHAR(temp);            if (utf) { BACKCHAR(temp); }
1013  #endif  #endif
1014            GETCHARTEST(d, temp);            GETCHARTEST(d, temp);
1015  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
# Line 980  for (;;) Line 1061  for (;;)
1061        if (clen > 0)        if (clen > 0)
1062          {          {
1063          BOOL OK;          BOOL OK;
1064            const pcre_uint32 *cp;
1065          const ucd_record * prop = GET_UCD(c);          const ucd_record * prop = GET_UCD(c);
1066          switch(code[1])          switch(code[1])
1067            {            {
# Line 993  for (;;) Line 1075  for (;;)
1075            break;            break;
1076
1077            case PT_GC:            case PT_GC:
1078            OK = _pcre_ucp_gentype[prop->chartype] == code[2];            OK = PRIV(ucp_gentype)[prop->chartype] == code[2];
1079            break;            break;
1080
1081            case PT_PC:            case PT_PC:
# Line 1007  for (;;) Line 1089  for (;;)
1089            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1090
1091            case PT_ALNUM:            case PT_ALNUM:
1092            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1093                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1094            break;            break;
1095
1096            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1097            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1098                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1099            break;            break;
1100
1101            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1102            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1103                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1104                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1105            break;            break;
1106
1107            case PT_WORD:            case PT_WORD:
1108            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1109                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1110                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1111            break;            break;
1112
1113              case PT_CLIST:
1114              cp = PRIV(ucd_caseless_sets) + prop->caseset;
1115              for (;;)
1116                {
1117                if (c < *cp) { OK = FALSE; break; }
1118                if (c == *cp++) { OK = TRUE; break; }
1119                }
1120              break;
1121
1122            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1123
# Line 1055  for (;;) Line 1146  for (;;)
1146        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1147        if (clen > 0)        if (clen > 0)
1148          {          {
1149          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1150                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1151                NLBLOCK->nltype == NLTYPE_FIXED &&
1152                NLBLOCK->nllen == 2 &&
1153                c == NLBLOCK->nl[0])
1154              {
1155              could_continue = partial_newline = TRUE;
1156              }
1157            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1158              (c < 256 &&              (c < 256 &&
1159                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1160                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1078  for (;;) Line 1177  for (;;)
1178        if (clen > 0)        if (clen > 0)
1179          {          {
1180          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1181                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1182                NLBLOCK->nltype == NLTYPE_FIXED &&
1183                NLBLOCK->nllen == 2 &&
1184                c == NLBLOCK->nl[0])
1185              {
1186              could_continue = partial_newline = TRUE;
1187              }
1188            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1189              (c < 256 &&              (c < 256 &&
1190                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1191                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1100  for (;;) Line 1207  for (;;)
1208        if (clen > 0)        if (clen > 0)
1209          {          {
1210          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1211                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1212                NLBLOCK->nltype == NLTYPE_FIXED &&
1213                NLBLOCK->nllen == 2 &&
1214                c == NLBLOCK->nl[0])
1215              {
1216              could_continue = partial_newline = TRUE;
1217              }
1218            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1219              (c < 256 &&              (c < 256 &&
1220                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1221                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1120  for (;;) Line 1235  for (;;)
1235        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1236        if (clen > 0)        if (clen > 0)
1237          {          {
1238          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1239                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1240                NLBLOCK->nltype == NLTYPE_FIXED &&
1241                NLBLOCK->nllen == 2 &&
1242                c == NLBLOCK->nl[0])
1243              {
1244              could_continue = partial_newline = TRUE;
1245              }
1246            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1247              (c < 256 &&              (c < 256 &&
1248                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1249                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
1250            {            {
1251            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1252              { ADD_NEW(state_offset + 4, 0); }              { ADD_NEW(state_offset + 1 + IMM2_SIZE + 1, 0); }
1253            else            else
1255            }            }
# Line 1137  for (;;) Line 1260  for (;;)
1260        case OP_TYPEUPTO:        case OP_TYPEUPTO:
1261        case OP_TYPEMINUPTO:        case OP_TYPEMINUPTO:
1262        case OP_TYPEPOSUPTO:        case OP_TYPEPOSUPTO:
1264        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1265        if (clen > 0)        if (clen > 0)
1266          {          {
1267          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if (d == OP_ANY && ptr + 1 >= md->end_subject &&
1268                (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
1269                NLBLOCK->nltype == NLTYPE_FIXED &&
1270                NLBLOCK->nllen == 2 &&
1271                c == NLBLOCK->nl[0])
1272              {
1273              could_continue = partial_newline = TRUE;
1274              }
1275            else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1276              (c < 256 &&              (c < 256 &&
1277                (d != OP_ANY || !IS_NEWLINE(ptr)) &&                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
1278                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
# Line 1152  for (;;) Line 1283  for (;;)
1283              next_active_state--;              next_active_state--;
1284              }              }
1285            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1286              { ADD_NEW(state_offset + 4, 0); }              { ADD_NEW(state_offset + 2 + IMM2_SIZE, 0); }
1287            else            else
1289            }            }
# Line 1174  for (;;) Line 1305  for (;;)
1305        if (clen > 0)        if (clen > 0)
1306          {          {
1307          BOOL OK;          BOOL OK;
1308            const pcre_uint32 *cp;
1309          const ucd_record * prop = GET_UCD(c);          const ucd_record * prop = GET_UCD(c);
1310          switch(code[2])          switch(code[2])
1311            {            {
# Line 1187  for (;;) Line 1319  for (;;)
1319            break;            break;
1320
1321            case PT_GC:            case PT_GC:
1322            OK = _pcre_ucp_gentype[prop->chartype] == code[3];            OK = PRIV(ucp_gentype)[prop->chartype] == code[3];
1323            break;            break;
1324
1325            case PT_PC:            case PT_PC:
# Line 1201  for (;;) Line 1333  for (;;)
1333            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1334
1335            case PT_ALNUM:            case PT_ALNUM:
1336            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1337                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1338            break;            break;
1339
1340            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1341            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1342                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1343            break;            break;
1344
1345            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1346            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1347                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1348                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1349            break;            break;
1350
1351            case PT_WORD:            case PT_WORD:
1352            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1353                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1354                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1355            break;            break;
1356
1357              case PT_CLIST:
1358              cp = PRIV(ucd_caseless_sets) + prop->caseset;
1359              for (;;)
1360                {
1361                if (c < *cp) { OK = FALSE; break; }
1362                if (c == *cp++) { OK = TRUE; break; }
1363                }
1364              break;
1365
1366            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1367
1368            default:            default:
# Line 1248  for (;;) Line 1389  for (;;)
1389        case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:        case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:
1390        count = current_state->count;  /* Already matched */        count = current_state->count;  /* Already matched */
1391        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1392        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0)
1393          {          {
1394          const uschar *nptr = ptr + clen;          int lgb, rgb;
1395            const pcre_uchar *nptr = ptr + clen;
1396          int ncount = 0;          int ncount = 0;
1397          if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)          if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)
1398            {            {
1399            active_count--;           /* Remove non-match possibility */            active_count--;           /* Remove non-match possibility */
1400            next_active_state--;            next_active_state--;
1401            }            }
1402            lgb = UCD_GRAPHBREAK(c);
1403          while (nptr < end_subject)          while (nptr < end_subject)
1404            {            {
1405            int nd;            dlen = 1;
1406            int ndlen = 1;            if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
1407            GETCHARLEN(nd, nptr, ndlen);            rgb = UCD_GRAPHBREAK(d);
1408            if (UCD_CATEGORY(nd) != ucp_M) break;            if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
1409            ncount++;            ncount++;
1410            nptr += ndlen;            lgb = rgb;
1411              nptr += dlen;
1412            }            }
1413          count++;          count++;
# Line 1283  for (;;) Line 1427  for (;;)
1427          int ncount = 0;          int ncount = 0;
1428          switch (c)          switch (c)
1429            {            {
1430            case 0x000b:            case CHAR_VT:
1431            case 0x000c:            case CHAR_FF:
1432            case 0x0085:            case CHAR_NEL:
1433    #ifndef EBCDIC
1434            case 0x2028:            case 0x2028:
1435            case 0x2029:            case 0x2029:
1436    #endif  /* Not EBCDIC */
1437            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1438            goto ANYNL01;            goto ANYNL01;
1439
1440            case 0x000d:            case CHAR_CR:
1441            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;            if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
1442            /* Fall through */            /* Fall through */
1443
1444            ANYNL01:            ANYNL01:
1445            case 0x000a:            case CHAR_LF:
1446            if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)            if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)
1447              {              {
1448              active_count--;           /* Remove non-match possibility */              active_count--;           /* Remove non-match possibility */
# Line 1323  for (;;) Line 1469  for (;;)
1469          BOOL OK;          BOOL OK;
1470          switch (c)          switch (c)
1471            {            {
1472            case 0x000a:            VSPACE_CASES:
case 0x000b:
case 0x000c:
case 0x000d:
case 0x0085:
case 0x2028:
case 0x2029:
1473            OK = TRUE;            OK = TRUE;
1474            break;            break;
1475
# Line 1362  for (;;) Line 1502  for (;;)
1502          BOOL OK;          BOOL OK;
1503          switch (c)          switch (c)
1504            {            {
1505            case 0x09:      /* HT */            HSPACE_CASES:
case 0x20:      /* SPACE */
case 0xa0:      /* NBSP */
case 0x1680:    /* OGHAM SPACE MARK */
case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
case 0x2000:    /* EN QUAD */
case 0x2001:    /* EM QUAD */
case 0x2002:    /* EN SPACE */
case 0x2003:    /* EM SPACE */
case 0x2004:    /* THREE-PER-EM SPACE */
case 0x2005:    /* FOUR-PER-EM SPACE */
case 0x2006:    /* SIX-PER-EM SPACE */
case 0x2007:    /* FIGURE SPACE */
case 0x2008:    /* PUNCTUATION SPACE */
case 0x2009:    /* THIN SPACE */
case 0x200A:    /* HAIR SPACE */
case 0x202f:    /* NARROW NO-BREAK SPACE */
case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
case 0x3000:    /* IDEOGRAPHIC SPACE */
1506            OK = TRUE;            OK = TRUE;
1507            break;            break;
1508
# Line 1421  for (;;) Line 1543  for (;;)
1543        if (clen > 0)        if (clen > 0)
1544          {          {
1545          BOOL OK;          BOOL OK;
1546            const pcre_uint32 *cp;
1547          const ucd_record * prop = GET_UCD(c);          const ucd_record * prop = GET_UCD(c);
1548          switch(code[2])          switch(code[2])
1549            {            {
# Line 1434  for (;;) Line 1557  for (;;)
1557            break;            break;
1558
1559            case PT_GC:            case PT_GC:
1560            OK = _pcre_ucp_gentype[prop->chartype] == code[3];            OK = PRIV(ucp_gentype)[prop->chartype] == code[3];
1561            break;            break;
1562
1563            case PT_PC:            case PT_PC:
# Line 1448  for (;;) Line 1571  for (;;)
1571            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1572
1573            case PT_ALNUM:            case PT_ALNUM:
1574            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1575                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1576            break;            break;
1577
1578            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1579            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1580                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1581            break;            break;
1582
1583            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1584            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1585                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1586                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1587            break;            break;
1588
1589            case PT_WORD:            case PT_WORD:
1590            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1591                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1592                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1593            break;            break;
1594
1595              case PT_CLIST:
1596              cp = PRIV(ucd_caseless_sets) + prop->caseset;
1597              for (;;)
1598                {
1599                if (c < *cp) { OK = FALSE; break; }
1600                if (c == *cp++) { OK = TRUE; break; }
1601                }
1602              break;
1603
1604            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1605
1606            default:            default:
# Line 1504  for (;;) Line 1636  for (;;)
1636        QS2:        QS2:
1637
1639        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0)
1640          {          {
1641          const uschar *nptr = ptr + clen;          int lgb, rgb;
1642            const pcre_uchar *nptr = ptr + clen;
1643          int ncount = 0;          int ncount = 0;
1644          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||
1645              codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)              codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)
# Line 1514  for (;;) Line 1647  for (;;)
1647            active_count--;           /* Remove non-match possibility */            active_count--;           /* Remove non-match possibility */
1648            next_active_state--;            next_active_state--;
1649            }            }
1650            lgb = UCD_GRAPHBREAK(c);
1651          while (nptr < end_subject)          while (nptr < end_subject)
1652            {            {
1653            int nd;            dlen = 1;
1654            int ndlen = 1;            if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
1655            GETCHARLEN(nd, nptr, ndlen);            rgb = UCD_GRAPHBREAK(d);
1656            if (UCD_CATEGORY(nd) != ucp_M) break;            if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
1657            ncount++;            ncount++;
1658            nptr += ndlen;            lgb = rgb;
1659              nptr += dlen;
1660            }            }
1662          }          }
# Line 1547  for (;;) Line 1682  for (;;)
1682          int ncount = 0;          int ncount = 0;
1683          switch (c)          switch (c)
1684            {            {
1685            case 0x000b:            case CHAR_VT:
1686            case 0x000c:            case CHAR_FF:
1687            case 0x0085:            case CHAR_NEL:
1688    #ifndef EBCDIC
1689            case 0x2028:            case 0x2028:
1690            case 0x2029:            case 0x2029:
1691    #endif  /* Not EBCDIC */
1692            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1693            goto ANYNL02;            goto ANYNL02;
1694
1695            case 0x000d:            case CHAR_CR:
1696            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;            if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
1697            /* Fall through */            /* Fall through */
1698
1699            ANYNL02:            ANYNL02:
1700            case 0x000a:            case CHAR_LF:
1701            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||
1702                codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)                codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)
1703              {              {
# Line 1595  for (;;) Line 1732  for (;;)
1732          BOOL OK;          BOOL OK;
1733          switch (c)          switch (c)
1734            {            {
1735            case 0x000a:            VSPACE_CASES:
case 0x000b:
case 0x000c:
case 0x000d:
case 0x0085:
case 0x2028:
case 0x2029:
1736            OK = TRUE;            OK = TRUE;
1737            break;            break;
1738
# Line 1641  for (;;) Line 1772  for (;;)
1772          BOOL OK;          BOOL OK;
1773          switch (c)          switch (c)
1774            {            {
1775            case 0x09:      /* HT */            HSPACE_CASES:
case 0x20:      /* SPACE */
case 0xa0:      /* NBSP */
case 0x1680:    /* OGHAM SPACE MARK */
case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
case 0x2000:    /* EN QUAD */
case 0x2001:    /* EM QUAD */
case 0x2002:    /* EN SPACE */
case 0x2003:    /* EM SPACE */
case 0x2004:    /* THREE-PER-EM SPACE */
case 0x2005:    /* FOUR-PER-EM SPACE */
case 0x2006:    /* SIX-PER-EM SPACE */
case 0x2007:    /* FIGURE SPACE */
case 0x2008:    /* PUNCTUATION SPACE */
case 0x2009:    /* THIN SPACE */
case 0x200A:    /* HAIR SPACE */
case 0x202f:    /* NARROW NO-BREAK SPACE */
case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
case 0x3000:    /* IDEOGRAPHIC SPACE */
1776            OK = TRUE;            OK = TRUE;
1777            break;            break;
1778
# Line 1688  for (;;) Line 1801  for (;;)
1801        case OP_PROP_EXTRA + OP_TYPEMINUPTO:        case OP_PROP_EXTRA + OP_TYPEMINUPTO:
1802        case OP_PROP_EXTRA + OP_TYPEPOSUPTO:        case OP_PROP_EXTRA + OP_TYPEPOSUPTO:
1803        if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)
1804          { ADD_ACTIVE(state_offset + 6, 0); }          { ADD_ACTIVE(state_offset + 1 + IMM2_SIZE + 3, 0); }
1805        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1806        if (clen > 0)        if (clen > 0)
1807          {          {
1808          BOOL OK;          BOOL OK;
1809            const pcre_uint32 *cp;
1810          const ucd_record * prop = GET_UCD(c);          const ucd_record * prop = GET_UCD(c);
1811          switch(code[4])          switch(code[1 + IMM2_SIZE + 1])
1812            {            {
1813            case PT_ANY:            case PT_ANY:
1814            OK = TRUE;            OK = TRUE;
# Line 1706  for (;;) Line 1820  for (;;)
1820            break;            break;
1821
1822            case PT_GC:            case PT_GC:
1823            OK = _pcre_ucp_gentype[prop->chartype] == code[5];            OK = PRIV(ucp_gentype)[prop->chartype] == code[1 + IMM2_SIZE + 2];
1824            break;            break;
1825
1826            case PT_PC:            case PT_PC:
1827            OK = prop->chartype == code[5];            OK = prop->chartype == code[1 + IMM2_SIZE + 2];
1828            break;            break;
1829
1830            case PT_SC:            case PT_SC:
1831            OK = prop->script == code[5];            OK = prop->script == code[1 + IMM2_SIZE + 2];
1832            break;            break;
1833
1834            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1835
1836            case PT_ALNUM:            case PT_ALNUM:
1837            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1838                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 PRIV(ucp_gentype)[prop->chartype] == ucp_N;
1839            break;            break;
1840
1841            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1842            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1843                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1844            break;            break;
1845
1846            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1847            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
1848                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1849                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1850            break;            break;
1851
1852            case PT_WORD:            case PT_WORD:
1853            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
1854                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
1855                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1856            break;            break;
1857
1858              case PT_CLIST:
1859              cp = PRIV(ucd_caseless_sets) + prop->caseset;
1860              for (;;)
1861                {
1862                if (c < *cp) { OK = FALSE; break; }
1863                if (c == *cp++) { OK = TRUE; break; }
1864                }
1865              break;
1866
1867            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1868
1869            default:            default:
# Line 1756  for (;;) Line 1879  for (;;)
1879              next_active_state--;              next_active_state--;
1880              }              }
1881            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1882              { ADD_NEW(state_offset + 6, 0); }              { ADD_NEW(state_offset + 1 + IMM2_SIZE + 3, 0); }
1883            else            else
1885            }            }
# Line 1769  for (;;) Line 1892  for (;;)
1892        case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:        case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:
1893        case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:        case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:
1894        if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)
1895          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
1896        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1897        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0)
1898          {          {
1899          const uschar *nptr = ptr + clen;          int lgb, rgb;
1900            const pcre_uchar *nptr = ptr + clen;
1901          int ncount = 0;          int ncount = 0;
1902          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)          if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)
1903            {            {
1904            active_count--;           /* Remove non-match possibility */            active_count--;           /* Remove non-match possibility */
1905            next_active_state--;            next_active_state--;
1906            }            }
1907            lgb = UCD_GRAPHBREAK(c);
1908          while (nptr < end_subject)          while (nptr < end_subject)
1909            {            {
1910            int nd;            dlen = 1;
1911            int ndlen = 1;            if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
1912            GETCHARLEN(nd, nptr, ndlen);            rgb = UCD_GRAPHBREAK(d);
1913            if (UCD_CATEGORY(nd) != ucp_M) break;            if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
1914            ncount++;            ncount++;
1915            nptr += ndlen;            lgb = rgb;
1916              nptr += dlen;
1917            }            }
1918            if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
1919                reset_could_continue = TRUE;
1920          if (++count >= GET2(code, 1))          if (++count >= GET2(code, 1))
1921            { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }            { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
1922          else          else
1924          }          }
# Line 1803  for (;;) Line 1931  for (;;)
1931        case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:        case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:
1932        case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:        case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:
1933        if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)
1934          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
1935        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1936        if (clen > 0)        if (clen > 0)
1937          {          {
1938          int ncount = 0;          int ncount = 0;
1939          switch (c)          switch (c)
1940            {            {
1941            case 0x000b:            case CHAR_VT:
1942            case 0x000c:            case CHAR_FF:
1943            case 0x0085:            case CHAR_NEL:
1944    #ifndef EBCDIC
1945            case 0x2028:            case 0x2028:
1946            case 0x2029:            case 0x2029:
1947    #endif  /* Not EBCDIC */
1948            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1949            goto ANYNL03;            goto ANYNL03;
1950
1951            case 0x000d:            case CHAR_CR:
1952            if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;            if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
1953            /* Fall through */            /* Fall through */
1954
1955            ANYNL03:            ANYNL03:
1956            case 0x000a:            case CHAR_LF:
1957            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)            if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)
1958              {              {
1959              active_count--;           /* Remove non-match possibility */              active_count--;           /* Remove non-match possibility */
1960              next_active_state--;              next_active_state--;
1961              }              }
1962            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1963              { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }              { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
1964            else            else
1966            break;            break;
# Line 1847  for (;;) Line 1977  for (;;)
1977        case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:        case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:
1978        case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:        case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:
1979        if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)
1980          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
1981        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1982        if (clen > 0)        if (clen > 0)
1983          {          {
1984          BOOL OK;          BOOL OK;
1985          switch (c)          switch (c)
1986            {            {
1987            case 0x000a:            VSPACE_CASES:
case 0x000b:
case 0x000c:
case 0x000d:
case 0x0085:
case 0x2028:
case 0x2029:
1988            OK = TRUE;            OK = TRUE;
1989            break;            break;
1990
# Line 1876  for (;;) Line 2000  for (;;)
2000              next_active_state--;              next_active_state--;
2001              }              }
2002            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2003              { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }              { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }
2004            else            else
2006            }            }
# Line 1889  for (;;) Line 2013  for (;;)
2013        case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:        case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:
2014        case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:        case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:
2015        if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)
2016          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
2017        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
2018        if (clen > 0)        if (clen > 0)
2019          {          {
2020          BOOL OK;          BOOL OK;
2021          switch (c)          switch (c)
2022            {            {
2023            case 0x09:      /* HT */            HSPACE_CASES:
case 0x20:      /* SPACE */
case 0xa0:      /* NBSP */
case 0x1680:    /* OGHAM SPACE MARK */
case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
case 0x2000:    /* EN QUAD */
case 0x2001:    /* EM QUAD */
case 0x2002:    /* EN SPACE */
case 0x2003:    /* EM SPACE */
case 0x2004:    /* THREE-PER-EM SPACE */
case 0x2005:    /* FOUR-PER-EM SPACE */
case 0x2006:    /* SIX-PER-EM SPACE */
case 0x2007:    /* FIGURE SPACE */
case 0x2008:    /* PUNCTUATION SPACE */
case 0x2009:    /* THIN SPACE */
case 0x200A:    /* HAIR SPACE */
case 0x202f:    /* NARROW NO-BREAK SPACE */
case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
case 0x3000:    /* IDEOGRAPHIC SPACE */
2024            OK = TRUE;            OK = TRUE;
2025            break;            break;
2026
# Line 1931  for (;;) Line 2037  for (;;)
2037              next_active_state--;              next_active_state--;
2038              }              }
2039            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2040              { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }              { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }
2041            else            else
2043            }            }
# Line 1950  for (;;) Line 2056  for (;;)
2056        break;        break;
2057
2058        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2059        case OP_CHARNC:        case OP_CHARI:
2060        if (clen == 0) break;        if (clen == 0) break;
2061
2062  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2063        if (utf8)        if (utf)
2064          {          {
2065          if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else          if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else
2066            {            {
2067            unsigned int othercase;            unsigned int othercase;
2068            if (c < 128) othercase = fcc[c]; else            if (c < 128)
2069                othercase = fcc[c];
2070            /* If we have Unicode property support, we can use it to test the            else
2071            other case of the character. */              /* If we have Unicode property support, we can use it to test the
2072                other case of the character. */
2073  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2074            othercase = UCD_OTHERCASE(c);              othercase = UCD_OTHERCASE(c);
2075  #else  #else
2076            othercase = NOTACHAR;              othercase = NOTACHAR;
2077  #endif  #endif
2078
2079            if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }            if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }
2080            }            }
2081          }          }
2082        else        else
2083  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2084          /* Not UTF mode */
/* Non-UTF-8 mode */
2085          {          {
2086          if (lcc[c] == lcc[d]) { ADD_NEW(state_offset + 2, 0); }          if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d))
2087              { ADD_NEW(state_offset + 2, 0); }
2088          }          }
2089        break;        break;
2090
# Line 1990  for (;;) Line 2096  for (;;)
2096        to wait for them to pass before continuing. */        to wait for them to pass before continuing. */
2097
2098        case OP_EXTUNI:        case OP_EXTUNI:
2099        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)        if (clen > 0)
2100          {          {
2101          const uschar *nptr = ptr + clen;          int lgb, rgb;
2102            const pcre_uchar *nptr = ptr + clen;
2103          int ncount = 0;          int ncount = 0;
2104            lgb = UCD_GRAPHBREAK(c);
2105          while (nptr < end_subject)          while (nptr < end_subject)
2106            {            {
2107            int nclen = 1;            dlen = 1;
2108            GETCHARLEN(c, nptr, nclen);            if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
2109            if (UCD_CATEGORY(c) != ucp_M) break;            rgb = UCD_GRAPHBREAK(d);
2110              if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
2111            ncount++;            ncount++;
2112            nptr += nclen;            lgb = rgb;
2113              nptr += dlen;
2114            }            }
2115            if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
2116                reset_could_continue = TRUE;
2118          }          }
2119        break;        break;
# Line 2015  for (;;) Line 2127  for (;;)
2127        case OP_ANYNL:        case OP_ANYNL:
2128        if (clen > 0) switch(c)        if (clen > 0) switch(c)
2129          {          {
2130          case 0x000b:          case CHAR_VT:
2131          case 0x000c:          case CHAR_FF:
2132          case 0x0085:          case CHAR_NEL:
2133    #ifndef EBCDIC
2134          case 0x2028:          case 0x2028:
2135          case 0x2029:          case 0x2029:
2136    #endif  /* Not EBCDIC */
2137          if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;          if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
2138
2139          case 0x000a:          case CHAR_LF:
2141          break;          break;
2142
2143          case 0x000d:          case CHAR_CR:
2144          if (ptr + 1 < end_subject && ptr[1] == 0x0a)          if (ptr + 1 >= end_subject)
2145              {
2147              if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
2148                reset_could_continue = TRUE;
2149              }
2150            else if (RAWUCHARTEST(ptr + 1) == CHAR_LF)
2151            {            {
2153            }            }
# Line 2043  for (;;) Line 2163  for (;;)
2163        case OP_NOT_VSPACE:        case OP_NOT_VSPACE:
2164        if (clen > 0) switch(c)        if (clen > 0) switch(c)
2165          {          {
2166          case 0x000a:          VSPACE_CASES:
case 0x000b:
case 0x000c:
case 0x000d:
case 0x0085:
case 0x2028:
case 0x2029:
2167          break;          break;
2168
2169          default:          default:
# Line 2062  for (;;) Line 2176  for (;;)
2176        case OP_VSPACE:        case OP_VSPACE:
2177        if (clen > 0) switch(c)        if (clen > 0) switch(c)
2178          {          {
2179          case 0x000a:          VSPACE_CASES:
case 0x000b:
case 0x000c:
case 0x000d:
case 0x0085:
case 0x2028:
case 0x2029:
2181          break;          break;
2182
2183          default: break;          default:
2184            break;
2185          }          }
2186        break;        break;
2187
# Line 2080  for (;;) Line 2189  for (;;)
2189        case OP_NOT_HSPACE:        case OP_NOT_HSPACE:
2190        if (clen > 0) switch(c)        if (clen > 0) switch(c)
2191          {          {
2192          case 0x09:      /* HT */          HSPACE_CASES:
case 0x20:      /* SPACE */
case 0xa0:      /* NBSP */
case 0x1680:    /* OGHAM SPACE MARK */
case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
case 0x2000:    /* EN QUAD */
case 0x2001:    /* EM QUAD */
case 0x2002:    /* EN SPACE */
case 0x2003:    /* EM SPACE */
case 0x2004:    /* THREE-PER-EM SPACE */
case 0x2005:    /* FOUR-PER-EM SPACE */
case 0x2006:    /* SIX-PER-EM SPACE */
case 0x2007:    /* FIGURE SPACE */
case 0x2008:    /* PUNCTUATION SPACE */
case 0x2009:    /* THIN SPACE */
case 0x200A:    /* HAIR SPACE */
case 0x202f:    /* NARROW NO-BREAK SPACE */
case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
case 0x3000:    /* IDEOGRAPHIC SPACE */
2193          break;          break;
2194
2195          default:          default:
# Line 2111  for (;;) Line 2202  for (;;)
2202        case OP_HSPACE:        case OP_HSPACE:
2203        if (clen > 0) switch(c)        if (clen > 0) switch(c)
2204          {          {
2205          case 0x09:      /* HT */          HSPACE_CASES:
case 0x20:      /* SPACE */
case 0xa0:      /* NBSP */
case 0x1680:    /* OGHAM SPACE MARK */
case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
case 0x2000:    /* EN QUAD */
case 0x2001:    /* EM QUAD */
case 0x2002:    /* EN SPACE */
case 0x2003:    /* EM SPACE */
case 0x2004:    /* THREE-PER-EM SPACE */
case 0x2005:    /* FOUR-PER-EM SPACE */
case 0x2006:    /* SIX-PER-EM SPACE */
case 0x2007:    /* FIGURE SPACE */
case 0x2008:    /* PUNCTUATION SPACE */
case 0x2009:    /* THIN SPACE */
case 0x200A:    /* HAIR SPACE */
case 0x202f:    /* NARROW NO-BREAK SPACE */
case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
case 0x3000:    /* IDEOGRAPHIC SPACE */
2207          break;          break;
2208
2209            default:
2210            break;
2211          }          }
2212        break;        break;
2213
2214        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2215        /* Match a negated single character. This is only used for one-byte        /* Match a negated single character casefully. */
characters, that is, we know that d < 256. The character we are
checking (c) can be multibyte. */
2216
2217        case OP_NOT:        case OP_NOT:
2218          if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); }
2219          break;
2220
2221          /*-----------------------------------------------------------------*/
2222          /* Match a negated single character caselessly. */
2223
2224          case OP_NOTI:
2225        if (clen > 0)        if (clen > 0)
2226          {          {
2227          unsigned int otherd = ((ims & PCRE_CASELESS) != 0)? fcc[d] : d;          unsigned int otherd;
2228          if (c != d && c != otherd) { ADD_NEW(state_offset + dlen + 1, 0); }  #ifdef SUPPORT_UTF
2229            if (utf && d >= 128)
2230              {
2231    #ifdef SUPPORT_UCP
2232              otherd = UCD_OTHERCASE(d);
2233    #endif  /* SUPPORT_UCP */
2234              }
2235            else
2236    #endif  /* SUPPORT_UTF */
2237            otherd = TABLE_GET(d, fcc, d);
2238            if (c != d && c != otherd)
2239              { ADD_NEW(state_offset + dlen + 1, 0); }
2240          }          }
2241        break;        break;
2242
2243        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2244          case OP_PLUSI:
2245          case OP_MINPLUSI:
2246          case OP_POSPLUSI:
2247          case OP_NOTPLUSI:
2248          case OP_NOTMINPLUSI:
2249          case OP_NOTPOSPLUSI:
2250          caseless = TRUE;
2251          codevalue -= OP_STARI - OP_STAR;
2252
2253          /* Fall through */
2254        case OP_PLUS:        case OP_PLUS:
2255        case OP_MINPLUS:        case OP_MINPLUS:
2256        case OP_POSPLUS:        case OP_POSPLUS:
# Line 2159  for (;;) Line 2261  for (;;)
2261        if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }
2262        if (clen > 0)        if (clen > 0)
2263          {          {
2264          unsigned int otherd = NOTACHAR;          pcre_uint32 otherd = NOTACHAR;
2265          if ((ims & PCRE_CASELESS) != 0)          if (caseless)
2266            {            {
2267  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2268            if (utf8 && d >= 128)            if (utf && d >= 128)
2269              {              {
2270  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2271              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2272  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2273              }              }
2274            else            else
2275  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2276            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2277            }            }
2278          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2279            {            {
# Line 2188  for (;;) Line 2290  for (;;)
2290        break;        break;
2291
2292        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2293          case OP_QUERYI:
2294          case OP_MINQUERYI:
2295          case OP_POSQUERYI:
2296          case OP_NOTQUERYI:
2297          case OP_NOTMINQUERYI:
2298          case OP_NOTPOSQUERYI:
2299          caseless = TRUE;
2300          codevalue -= OP_STARI - OP_STAR;
2301          /* Fall through */
2302        case OP_QUERY:        case OP_QUERY:
2303        case OP_MINQUERY:        case OP_MINQUERY:
2304        case OP_POSQUERY:        case OP_POSQUERY:
# Line 2197  for (;;) Line 2308  for (;;)
2308        ADD_ACTIVE(state_offset + dlen + 1, 0);        ADD_ACTIVE(state_offset + dlen + 1, 0);
2309        if (clen > 0)        if (clen > 0)
2310          {          {
2311          unsigned int otherd = NOTACHAR;          pcre_uint32 otherd = NOTACHAR;
2312          if ((ims & PCRE_CASELESS) != 0)          if (caseless)
2313            {            {
2314  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2315            if (utf8 && d >= 128)            if (utf && d >= 128)
2316              {              {
2317  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2318              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2319  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2320              }              }
2321            else            else
2322  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2323            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2324            }            }
2325          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2326            {            {
# Line 2224  for (;;) Line 2335  for (;;)
2335        break;        break;
2336
2337        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2338          case OP_STARI:
2339          case OP_MINSTARI:
2340          case OP_POSSTARI:
2341          case OP_NOTSTARI:
2342          case OP_NOTMINSTARI:
2343          case OP_NOTPOSSTARI:
2344          caseless = TRUE;
2345          codevalue -= OP_STARI - OP_STAR;
2346          /* Fall through */
2347        case OP_STAR:        case OP_STAR:
2348        case OP_MINSTAR:        case OP_MINSTAR:
2349        case OP_POSSTAR:        case OP_POSSTAR:
# Line 2233  for (;;) Line 2353  for (;;)
2353        ADD_ACTIVE(state_offset + dlen + 1, 0);        ADD_ACTIVE(state_offset + dlen + 1, 0);
2354        if (clen > 0)        if (clen > 0)
2355          {          {
2356          unsigned int otherd = NOTACHAR;          pcre_uint32 otherd = NOTACHAR;
2357          if ((ims & PCRE_CASELESS) != 0)          if (caseless)
2358            {            {
2359  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2360            if (utf8 && d >= 128)            if (utf && d >= 128)
2361              {              {
2362  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2363              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2364  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2365              }              }
2366            else            else
2367  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2368            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2369            }            }
2370          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2371            {            {
# Line 2260  for (;;) Line 2380  for (;;)
2380        break;        break;
2381
2382        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2383          case OP_EXACTI:
2384          case OP_NOTEXACTI:
2385          caseless = TRUE;
2386          codevalue -= OP_STARI - OP_STAR;
2387          /* Fall through */
2388        case OP_EXACT:        case OP_EXACT:
2389        case OP_NOTEXACT:        case OP_NOTEXACT:
2390        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
2391        if (clen > 0)        if (clen > 0)
2392          {          {
2393          unsigned int otherd = NOTACHAR;          pcre_uint32 otherd = NOTACHAR;
2394          if ((ims & PCRE_CASELESS) != 0)          if (caseless)
2395            {            {
2396  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2397            if (utf8 && d >= 128)            if (utf && d >= 128)
2398              {              {
2399  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2400              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2401  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2402              }              }
2403            else            else
2404  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2405            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2406            }            }
2407          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2408            {            {
2409            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2410              { ADD_NEW(state_offset + dlen + 3, 0); }              { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }
2411            else            else
2413            }            }
# Line 2290  for (;;) Line 2415  for (;;)
2415        break;        break;
2416
2417        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2418          case OP_UPTOI:
2419          case OP_MINUPTOI:
2420          case OP_POSUPTOI:
2421          case OP_NOTUPTOI:
2422          case OP_NOTMINUPTOI:
2423          case OP_NOTPOSUPTOI:
2424          caseless = TRUE;
2425          codevalue -= OP_STARI - OP_STAR;
2426          /* Fall through */
2427        case OP_UPTO:        case OP_UPTO:
2428        case OP_MINUPTO:        case OP_MINUPTO:
2429        case OP_POSUPTO:        case OP_POSUPTO:
2430        case OP_NOTUPTO:        case OP_NOTUPTO:
2431        case OP_NOTMINUPTO:        case OP_NOTMINUPTO:
2432        case OP_NOTPOSUPTO:        case OP_NOTPOSUPTO:
2433        ADD_ACTIVE(state_offset + dlen + 3, 0);        ADD_ACTIVE(state_offset + dlen + 1 + IMM2_SIZE, 0);
2434        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
2435        if (clen > 0)        if (clen > 0)
2436          {          {
2437          unsigned int otherd = NOTACHAR;          pcre_uint32 otherd = NOTACHAR;
2438          if ((ims & PCRE_CASELESS) != 0)          if (caseless)
2439            {            {
2440  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
2441            if (utf8 && d >= 128)            if (utf && d >= 128)
2442              {              {
2443  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2444              otherd = UCD_OTHERCASE(d);              otherd = UCD_OTHERCASE(d);
2445  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2446              }              }
2447            else            else
2448  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF */
2449            otherd = fcc[d];            otherd = TABLE_GET(d, fcc, d);
2450            }            }
2451          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2452            {            {
# Line 2322  for (;;) Line 2456  for (;;)
2456              next_active_state--;              next_active_state--;
2457              }              }
2458            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2459              { ADD_NEW(state_offset + dlen + 3, 0); }              { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }
2460            else            else
2462            }            }
# Line 2339  for (;;) Line 2473  for (;;)
2473          {          {
2474          BOOL isinclass = FALSE;          BOOL isinclass = FALSE;
2475          int next_state_offset;          int next_state_offset;
2476          const uschar *ecode;          const pcre_uchar *ecode;
2477
2478          /* For a simple class, there is always just a 32-byte table, and we          /* For a simple class, there is always just a 32-byte table, and we
2479          can set isinclass from it. */          can set isinclass from it. */
2480
2481          if (codevalue != OP_XCLASS)          if (codevalue != OP_XCLASS)
2482            {            {
2483            ecode = code + 33;            ecode = code + 1 + (32 / sizeof(pcre_uchar));
2484            if (clen > 0)            if (clen > 0)
2485              {              {
2486              isinclass = (c > 255)? (codevalue == OP_NCLASS) :              isinclass = (c > 255)? (codevalue == OP_NCLASS) :
2487                ((code[1 + c/8] & (1 << (c&7))) != 0);                ((((pcre_uint8 *)(code + 1))[c/8] & (1 << (c&7))) != 0);
2488              }              }
2489            }            }
2490
# Line 2361  for (;;) Line 2495  for (;;)
2495          else          else
2496           {           {
2497           ecode = code + GET(code, 1);           ecode = code + GET(code, 1);
2498           if (clen > 0) isinclass = _pcre_xclass(c, code + 1 + LINK_SIZE);           if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf);
2499           }           }
2500
2501          /* At this point, isinclass is set for all kinds of class, and ecode          /* At this point, isinclass is set for all kinds of class, and ecode
# Line 2395  for (;;) Line 2529  for (;;)
2529            case OP_CRMINRANGE:            case OP_CRMINRANGE:
2530            count = current_state->count;  /* Already matched */            count = current_state->count;  /* Already matched */
2531            if (count >= GET2(ecode, 1))            if (count >= GET2(ecode, 1))
2532              { ADD_ACTIVE(next_state_offset + 5, 0); }              { ADD_ACTIVE(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
2533            if (isinclass)            if (isinclass)
2534              {              {
2535              int max = GET2(ecode, 3);              int max = GET2(ecode, 1 + IMM2_SIZE);
2536              if (++count >= max && max != 0)   /* Max 0 => no limit */              if (++count >= max && max != 0)   /* Max 0 => no limit */
2537                { ADD_NEW(next_state_offset + 5, 0); }                { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
2538              else              else
2540              }              }
# Line 2431  for (;;) Line 2565  for (;;)
2565          int rc;          int rc;
2566          int local_offsets[2];          int local_offsets[2];
2567          int local_workspace[1000];          int local_workspace[1000];
2568          const uschar *endasscode = code + GET(code, 1);          const pcre_uchar *endasscode = code + GET(code, 1);
2569
2570          while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);          while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
2571
# Line 2444  for (;;) Line 2578  for (;;)
2578            sizeof(local_offsets)/sizeof(int),    /* size of same */            sizeof(local_offsets)/sizeof(int),    /* size of same */
2579            local_workspace,                      /* workspace vector */            local_workspace,                      /* workspace vector */
2580            sizeof(local_workspace)/sizeof(int),  /* size of same */            sizeof(local_workspace)/sizeof(int),  /* size of same */
2581            ims,                                  /* the current ims flags */            rlevel);                              /* function recursion level */
rlevel,                               /* function recursion level */
recursing);                           /* pass on regex recursion */
2582
2583          if (rc == PCRE_ERROR_DFA_UITEM) return rc;          if (rc == PCRE_ERROR_DFA_UITEM) return rc;
2584          if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))          if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))
# Line 2470  for (;;) Line 2602  for (;;)
2603            {            {
2604            rrc = 0;            rrc = 0;
2605            if (pcre_callout != NULL)            if (PUBL(callout) != NULL)
2606              {              {
2607              pcre_callout_block cb;              PUBL(callout_block) cb;
2608              cb.version          = 1;   /* Version 1 of the callout block */              cb.version          = 1;   /* Version 1 of the callout block */
2610              cb.offset_vector    = offsets;              cb.offset_vector    = offsets;
2611    #if defined COMPILE_PCRE8
2612              cb.subject          = (PCRE_SPTR)start_subject;              cb.subject          = (PCRE_SPTR)start_subject;
2613    #elif defined COMPILE_PCRE16
2614                cb.subject          = (PCRE_SPTR16)start_subject;
2615    #elif defined COMPILE_PCRE32
2616                cb.subject          = (PCRE_SPTR32)start_subject;
2617    #endif
2618              cb.subject_length   = (int)(end_subject - start_subject);              cb.subject_length   = (int)(end_subject - start_subject);
2619              cb.start_match      = (int)(current_subject - start_subject);              cb.start_match      = (int)(current_subject - start_subject);
2620              cb.current_position = (int)(ptr - start_subject);              cb.current_position = (int)(ptr - start_subject);
# Line 2485  for (;;) Line 2623  for (;;)
2623              cb.capture_top      = 1;              cb.capture_top      = 1;
2624              cb.capture_last     = -1;              cb.capture_last     = -1;
2625              cb.callout_data     = md->callout_data;              cb.callout_data     = md->callout_data;
2626              if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */              cb.mark             = NULL;   /* No (*MARK) support */
2627                if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc;   /* Abandon */
2628              }              }
2629            if (rrc > 0) break;                      /* Fail this thread */            if (rrc > 0) break;                      /* Fail this thread */
2630            code += _pcre_OP_lengths[OP_CALLOUT];    /* Skip callout data */            code += PRIV(OP_lengths)[OP_CALLOUT];    /* Skip callout data */
2631            }            }
2632
# Line 2509  for (;;) Line 2648  for (;;)
2648
2649          else if (condcode == OP_RREF || condcode == OP_NRREF)          else if (condcode == OP_RREF || condcode == OP_NRREF)
2650            {            {
2651            int value = GET2(code, LINK_SIZE+2);            int value = GET2(code, LINK_SIZE + 2);
2652            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
2653            if (recursing > 0)            if (md->recursive != NULL)
2656            }            }
2657
# Line 2521  for (;;) Line 2660  for (;;)
2660          else          else
2661            {            {
2662            int rc;            int rc;
2663            const uschar *asscode = code + LINK_SIZE + 1;            const pcre_uchar *asscode = code + LINK_SIZE + 1;
2664            const uschar *endasscode = asscode + GET(asscode, 1);            const pcre_uchar *endasscode = asscode + GET(asscode, 1);
2665
2666            while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);            while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
2667
# Line 2535  for (;;) Line 2674  for (;;)
2674              sizeof(local_offsets)/sizeof(int),    /* size of same */              sizeof(local_offsets)/sizeof(int),    /* size of same */
2675              local_workspace,                      /* workspace vector */              local_workspace,                      /* workspace vector */
2676              sizeof(local_workspace)/sizeof(int),  /* size of same */              sizeof(local_workspace)/sizeof(int),  /* size of same */
2677              ims,                                  /* the current ims flags */              rlevel);                              /* function recursion level */
rlevel,                               /* function recursion level */
recursing);                           /* pass on regex recursion */
2678
2679            if (rc == PCRE_ERROR_DFA_UITEM) return rc;            if (rc == PCRE_ERROR_DFA_UITEM) return rc;
2680            if ((rc >= 0) ==            if ((rc >= 0) ==
# Line 2552  for (;;) Line 2689  for (;;)
2689        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2690        case OP_RECURSE:        case OP_RECURSE:
2691          {          {
2692            dfa_recursion_info *ri;
2693          int local_offsets[1000];          int local_offsets[1000];
2694          int local_workspace[1000];          int local_workspace[1000];
2695            const pcre_uchar *callpat = start_code + GET(code, 1);
2696            int recno = (callpat == md->start_code)? 0 :
2698          int rc;          int rc;
2699
2700          DPRINTF(("%.*sStarting regex recursion %d\n", rlevel*2-2, SP,          DPRINTF(("%.*sStarting regex recursion\n", rlevel*2-2, SP));
2701            recursing + 1));
2702            /* Check for repeating a recursion without advancing the subject
2703            pointer. This should catch convoluted mutual recursions. (Some simple
2704            cases are caught at compile time.) */
2705
2706            for (ri = md->recursive; ri != NULL; ri = ri->prevrec)
2707              if (recno == ri->group_num && ptr == ri->subject_position)
2708                return PCRE_ERROR_RECURSELOOP;
2709
2710            /* Remember this recursion and where we started it so as to
2711            catch infinite loops. */
2712
2713            new_recursive.group_num = recno;
2714            new_recursive.subject_position = ptr;
2715            new_recursive.prevrec = md->recursive;
2716            md->recursive = &new_recursive;
2717
2718          rc = internal_dfa_exec(          rc = internal_dfa_exec(
2719            md,                                   /* fixed match data */            md,                                   /* fixed match data */
2720            start_code + GET(code, 1),            /* this subexpression's code */            callpat,                              /* this subexpression's code */
2721            ptr,                                  /* where we currently are */            ptr,                                  /* where we currently are */
2722            (int)(ptr - start_subject),           /* start offset */            (int)(ptr - start_subject),           /* start offset */
2723            local_offsets,                        /* offset vector */            local_offsets,                        /* offset vector */
2724            sizeof(local_offsets)/sizeof(int),    /* size of same */            sizeof(local_offsets)/sizeof(int),    /* size of same */
2725            local_workspace,                      /* workspace vector */            local_workspace,                      /* workspace vector */
2726            sizeof(local_workspace)/sizeof(int),  /* size of same */            sizeof(local_workspace)/sizeof(int),  /* size of same */
2727            ims,                                  /* the current ims flags */            rlevel);                              /* function recursion level */
rlevel,                               /* function recursion level */
recursing + 1);                       /* regex recurse level */
2728
2729          DPRINTF(("%.*sReturn from regex recursion %d: rc=%d\n", rlevel*2-2, SP,          md->recursive = new_recursive.prevrec;  /* Done this recursion */
2730            recursing + 1, rc));
2731            DPRINTF(("%.*sReturn from regex recursion: rc=%d\n", rlevel*2-2, SP,
2732              rc));
2733
2734          /* Ran out of internal offsets */          /* Ran out of internal offsets */
2735
# Line 2587  for (;;) Line 2743  for (;;)
2743            {            {
2744            for (rc = rc*2 - 2; rc >= 0; rc -= 2)            for (rc = rc*2 - 2; rc >= 0; rc -= 2)
2745              {              {
const uschar *p = start_subject + local_offsets[rc];
const uschar *pp = start_subject + local_offsets[rc+1];
2746              int charcount = local_offsets[rc+1] - local_offsets[rc];              int charcount = local_offsets[rc+1] - local_offsets[rc];
2747              while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;  #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2748                if (utf)
2749                  {
2750                  const pcre_uchar *p = start_subject + local_offsets[rc];
2751                  const pcre_uchar *pp = start_subject + local_offsets[rc+1];
2752                  while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
2753                  }
2754    #endif
2755              if (charcount > 0)              if (charcount > 0)
2756                {                {
# Line 2606  for (;;) Line 2767  for (;;)
2767        break;        break;
2768
2769        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2770          case OP_BRAPOS:
2771          case OP_SBRAPOS:
2772          case OP_CBRAPOS:
2773          case OP_SCBRAPOS:
2774          case OP_BRAPOSZERO:
2775            {
2776            int charcount, matched_count;
2777            const pcre_uchar *local_ptr = ptr;
2778            BOOL allow_zero;
2779
2780            if (codevalue == OP_BRAPOSZERO)
2781              {
2782              allow_zero = TRUE;
2783              codevalue = *(++code);  /* Codevalue will be one of above BRAs */
2784              }
2785            else allow_zero = FALSE;
2786
2787            /* Loop to match the subpattern as many times as possible as if it were
2788            a complete pattern. */
2789
2790            for (matched_count = 0;; matched_count++)
2791              {
2792              int local_offsets[2];
2793              int local_workspace[1000];
2794
2795              int rc = internal_dfa_exec(
2796                md,                                   /* fixed match data */
2797                code,                                 /* this subexpression's code */
2798                local_ptr,                            /* where we currently are */
2799                (int)(ptr - start_subject),           /* start offset */
2800                local_offsets,                        /* offset vector */
2801                sizeof(local_offsets)/sizeof(int),    /* size of same */
2802                local_workspace,                      /* workspace vector */
2803                sizeof(local_workspace)/sizeof(int),  /* size of same */
2804                rlevel);                              /* function recursion level */
2805
2806              /* Failed to match */
2807
2808              if (rc < 0)
2809                {
2810                if (rc != PCRE_ERROR_NOMATCH) return rc;
2811                break;
2812                }
2813
2814              /* Matched: break the loop if zero characters matched. */
2815
2816              charcount = local_offsets[1] - local_offsets[0];
2817              if (charcount == 0) break;
2818              local_ptr += charcount;    /* Advance temporary position ptr */
2819              }
2820
2821            /* At this point we have matched the subpattern matched_count
2822            times, and local_ptr is pointing to the character after the end of the
2823            last match. */
2824
2825            if (matched_count > 0 || allow_zero)
2826              {
2827              const pcre_uchar *end_subpattern = code;
2828              int next_state_offset;
2829
2830              do { end_subpattern += GET(end_subpattern, 1); }
2831                while (*end_subpattern == OP_ALT);
2832              next_state_offset =
2833                (int)(end_subpattern - start_code + LINK_SIZE + 1);
2834
2835              /* Optimization: if there are no more active states, and there
2836              are no new states yet set up, then skip over the subject string
2837              right here, to save looping. Otherwise, set up the new state to swing
2838              into action when the end of the matched substring is reached. */
2839
2840              if (i + 1 >= active_count && new_count == 0)
2841                {
2842                ptr = local_ptr;
2843                clen = 0;
2845                }
2846              else
2847                {
2848                const pcre_uchar *p = ptr;
2849                const pcre_uchar *pp = local_ptr;
2850                charcount = (int)(pp - p);
2851    #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2852                if (utf) while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
2853    #endif
2854                ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
2855                }
2856              }
2857            }
2858          break;
2859
2860          /*-----------------------------------------------------------------*/
2861        case OP_ONCE:        case OP_ONCE:
2862          case OP_ONCE_NC:
2863          {          {
2864          int local_offsets[2];          int local_offsets[2];
2865          int local_workspace[1000];          int local_workspace[1000];
# Line 2620  for (;;) Line 2873  for (;;)
2873            sizeof(local_offsets)/sizeof(int),    /* size of same */            sizeof(local_offsets)/sizeof(int),    /* size of same */
2874            local_workspace,                      /* workspace vector */            local_workspace,                      /* workspace vector */
2875            sizeof(local_workspace)/sizeof(int),  /* size of same */            sizeof(local_workspace)/sizeof(int),  /* size of same */
2876            ims,                                  /* the current ims flags */            rlevel);                              /* function recursion level */
rlevel,                               /* function recursion level */
recursing);                           /* pass on regex recursion */
2877
2878          if (rc >= 0)          if (rc >= 0)
2879            {            {
2880            const uschar *end_subpattern = code;            const pcre_uchar *end_subpattern = code;
2881            int charcount = local_offsets[1] - local_offsets[0];            int charcount = local_offsets[1] - local_offsets[0];
2882            int next_state_offset, repeat_state_offset;            int next_state_offset, repeat_state_offset;
2883
# Line 2656  for (;;) Line 2907  for (;;)
2907            /* Optimization: if there are no more active states, and there            /* Optimization: if there are no more active states, and there
2908            are no new states yet set up, then skip over the subject string            are no new states yet set up, then skip over the subject string
2909            right here, to save looping. Otherwise, set up the new state to swing            right here, to save looping. Otherwise, set up the new state to swing
2910            into action when the end of the substring is reached. */            into action when the end of the matched substring is reached. */
2911
2912            else if (i + 1 >= active_count && new_count == 0)            else if (i + 1 >= active_count && new_count == 0)
2913              {              {
# Line 2679  for (;;) Line 2930  for (;;)
2930              }              }
2931            else            else
2932              {              {
2933              const uschar *p = start_subject + local_offsets[0];  #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2934              const uschar *pp = start_subject + local_offsets[1];              if (utf)
2935              while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;                {
2936                  const pcre_uchar *p = start_subject + local_offsets[0];
2937                  const pcre_uchar *pp = start_subject + local_offsets[1];
2938                  while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
2939                  }
2940    #endif
2942              if (repeat_state_offset >= 0)              if (repeat_state_offset >= 0)
2943                { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }                { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }
2944              }              }

2945            }            }
2946          else if (rc != PCRE_ERROR_NOMATCH) return rc;          else if (rc != PCRE_ERROR_NOMATCH) return rc;
2947          }          }
# Line 2698  for (;;) Line 2953  for (;;)
2953
2954        case OP_CALLOUT:        case OP_CALLOUT:
2955        rrc = 0;        rrc = 0;
2956        if (pcre_callout != NULL)        if (PUBL(callout) != NULL)
2957          {          {
2958          pcre_callout_block cb;          PUBL(callout_block) cb;
2959          cb.version          = 1;   /* Version 1 of the callout block */          cb.version          = 1;   /* Version 1 of the callout block */
2960          cb.callout_number   = code[1];          cb.callout_number   = code[1];
2961          cb.offset_vector    = offsets;          cb.offset_vector    = offsets;
2962    #if defined COMPILE_PCRE8
2963          cb.subject          = (PCRE_SPTR)start_subject;          cb.subject          = (PCRE_SPTR)start_subject;
2964    #elif defined COMPILE_PCRE16
2965            cb.subject          = (PCRE_SPTR16)start_subject;
2966    #elif defined COMPILE_PCRE32
2967            cb.subject          = (PCRE_SPTR32)start_subject;
2968    #endif
2969          cb.subject_length   = (int)(end_subject - start_subject);          cb.subject_length   = (int)(end_subject - start_subject);
2970          cb.start_match      = (int)(current_subject - start_subject);          cb.start_match      = (int)(current_subject - start_subject);
2971          cb.current_position = (int)(ptr - start_subject);          cb.current_position = (int)(ptr - start_subject);
# Line 2713  for (;;) Line 2974  for (;;)
2974          cb.capture_top      = 1;          cb.capture_top      = 1;
2975          cb.capture_last     = -1;          cb.capture_last     = -1;
2976          cb.callout_data     = md->callout_data;          cb.callout_data     = md->callout_data;
2977          if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */          cb.mark             = NULL;   /* No (*MARK) support */
2978            if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc;   /* Abandon */
2979          }          }
2980        if (rrc == 0)        if (rrc == 0)
2981          { ADD_ACTIVE(state_offset + _pcre_OP_lengths[OP_CALLOUT], 0); }          { ADD_ACTIVE(state_offset + PRIV(OP_lengths)[OP_CALLOUT], 0); }
2982        break;        break;
2983
2984
# Line 2745  for (;;) Line 3007  for (;;)
3007    if (new_count <= 0)    if (new_count <= 0)
3008      {      {
3009      if (rlevel == 1 &&                               /* Top level, and */      if (rlevel == 1 &&                               /* Top level, and */
3010          could_continue &&                            /* Some could go on */          could_continue &&                            /* Some could go on, and */
3011          forced_fail != workspace[1] &&               /* Not all forced fail & */          forced_fail != workspace[1] &&               /* Not all forced fail & */
3012          (                                            /* either... */          (                                            /* either... */
3013          (md->moptions & PCRE_PARTIAL_HARD) != 0      /* Hard partial */          (md->moptions & PCRE_PARTIAL_HARD) != 0      /* Hard partial */
# Line 2753  for (;;) Line 3015  for (;;)
3015          ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */          ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */
3016           match_count < 0)                            /* no matches */           match_count < 0)                            /* no matches */
3017          ) &&                                         /* And... */          ) &&                                         /* And... */
3018          ptr >= end_subject &&                  /* Reached end of subject */          (
3019          ptr > md->start_used_ptr)              /* Inspected non-empty string */          partial_newline ||                           /* Either partial NL */
3020              (                                          /* or ... */
3021              ptr >= end_subject &&                /* End of subject and */
3022              ptr > md->start_used_ptr)            /* Inspected non-empty string */
3023              )
3024            )
3025        {        {
3026        if (offsetcount >= 2)        if (offsetcount >= 2)
3027          {          {
# Line 2813  Returns:          > 0 => number of match Line 3080  Returns:          > 0 => number of match
3080                   < -1 => some kind of unexpected problem                   < -1 => some kind of unexpected problem
3081  */  */
3082
3083    #if defined COMPILE_PCRE8
3084  PCRE_EXP_DEFN int PCRE_CALL_CONVENTION  PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
3085  pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,  pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,
3086    const char *subject, int length, int start_offset, int options, int *offsets,    const char *subject, int length, int start_offset, int options, int *offsets,
3087    int offsetcount, int *workspace, int wscount)    int offsetcount, int *workspace, int wscount)
3088    #elif defined COMPILE_PCRE16
3089    PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
3090    pcre16_dfa_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
3091      PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets,
3092      int offsetcount, int *workspace, int wscount)
3093    #elif defined COMPILE_PCRE32
3094    PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
3095    pcre32_dfa_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
3096      PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets,
3097      int offsetcount, int *workspace, int wscount)
3098    #endif
3099  {  {
3100  real_pcre *re = (real_pcre *)argument_re;  REAL_PCRE *re = (REAL_PCRE *)argument_re;
3101  dfa_match_data match_block;  dfa_match_data match_block;
3102  dfa_match_data *md = &match_block;  dfa_match_data *md = &match_block;
3103  BOOL utf8, anchored, startline, firstline;  BOOL utf, anchored, startline, firstline;
3104  const uschar *current_subject, *end_subject, *lcc;  const pcre_uchar *current_subject, *end_subject;

pcre_study_data internal_study;
3105  const pcre_study_data *study = NULL;  const pcre_study_data *study = NULL;
real_pcre internal_re;
3106
3107  const uschar *req_byte_ptr;  const pcre_uchar *req_char_ptr;
3108  const uschar *start_bits = NULL;  const pcre_uint8 *start_bits = NULL;
3109  BOOL first_byte_caseless = FALSE;  BOOL has_first_char = FALSE;
3110  BOOL req_byte_caseless = FALSE;  BOOL has_req_char = FALSE;
3111  int first_byte = -1;  pcre_uchar first_char = 0;
3112  int req_byte = -1;  pcre_uchar first_char2 = 0;
3113  int req_byte2 = -1;  pcre_uchar req_char = 0;
3114    pcre_uchar req_char2 = 0;
3115  int newline;  int newline;
3116
3117  /* Plausibility checks */  /* Plausibility checks */
# Line 2846  if (offsetcount < 0) return PCRE_ERROR_B Line 3123  if (offsetcount < 0) return PCRE_ERROR_B
3123  if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE;  if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE;
3124  if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;  if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;
3125
3126  /* We need to find the pointer to any study data before we test for byte  /* Check that the first field in the block is the magic number. If it is not,
3127  flipping, so we scan the extra_data block first. This may set two fields in the  return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to
3128  match block, so we must initialize them beforehand. However, the other fields  REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which
3129  in the match block must not be set until after the byte flipping. */  means that the pattern is likely compiled with different endianness. */
3130
3131    if (re->magic_number != MAGIC_NUMBER)
3132      return re->magic_number == REVERSED_MAGIC_NUMBER?
3134    if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
3135
3136    /* If restarting after a partial match, do some sanity checks on the contents
3137    of the workspace. */
3138
3139    if ((options & PCRE_DFA_RESTART) != 0)
3140      {
3141      if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 ||
3142        workspace[1] > (wscount - 2)/INTS_PER_STATEBLOCK)
3144      }
3145
3146    /* Set up study, callout, and table data */
3147
3148  md->tables = re->tables;  md->tables = re->tables;
3149  md->callout_data = NULL;  md->callout_data = NULL;
# Line 2868  if (extra_data != NULL) Line 3162  if (extra_data != NULL)
3162      md->tables = extra_data->tables;      md->tables = extra_data->tables;
3163    }    }
3164
/* Check that the first field in the block is the magic number. If it is not,
test for a regex that was compiled on a host of opposite endianness. If this is
the case, flipped values are put in internal_re and internal_study if there was
study data too. */

if (re->magic_number != MAGIC_NUMBER)
{
re = _pcre_try_flipped(re, &internal_re, study, &internal_study);
if (re == NULL) return PCRE_ERROR_BADMAGIC;
if (study != NULL) study = &internal_study;
}

3165  /* Set some local values */  /* Set some local values */
3166
3167  current_subject = (const unsigned char *)subject + start_offset;  current_subject = (const pcre_uchar *)subject + start_offset;
3168  end_subject = (const unsigned char *)subject + length;  end_subject = (const pcre_uchar *)subject + length;
3169  req_byte_ptr = current_subject - 1;  req_char_ptr = current_subject - 1;
3170
3171  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3172  utf8 = (re->options & PCRE_UTF8) != 0;  /* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */
3173    utf = (re->options & PCRE_UTF8) != 0;
3174  #else  #else
3175  utf8 = FALSE;  utf = FALSE;
3176  #endif  #endif
3177
3178  anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||  anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||
# Line 2897  anchored = (options & (PCRE_ANCHORED|PCR Line 3180  anchored = (options & (PCRE_ANCHORED|PCR
3180
3181  /* The remaining fixed data for passing around. */  /* The remaining fixed data for passing around. */
3182
3183  md->start_code = (const uschar *)argument_re +  md->start_code = (const pcre_uchar *)argument_re +
3184      re->name_table_offset + re->name_count * re->name_entry_size;      re->name_table_offset + re->name_count * re->name_entry_size;
3185  md->start_subject = (const unsigned char *)subject;  md->start_subject = (const pcre_uchar *)subject;
3186  md->end_subject = end_subject;  md->end_subject = end_subject;
3187  md->start_offset = start_offset;  md->start_offset = start_offset;
3188  md->moptions = options;  md->moptions = options;
# Line 2960  else Line 3243  else
3243  /* Check a UTF-8 string if required. Unfortunately there's no way of passing  /* Check a UTF-8 string if required. Unfortunately there's no way of passing
3244  back the character offset. */  back the character offset. */
3245
3246  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3247  if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)  if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
3248    {    {
3249    int tb;    int erroroffset;
3250    if ((tb = _pcre_valid_utf8((uschar *)subject, length)) >= 0)    int errorcode = PRIV(valid_utf)((pcre_uchar *)subject, length, &erroroffset);
3251      return (tb == length && (options & PCRE_PARTIAL_HARD) != 0)?    if (errorcode != 0)
if (start_offset > 0 && start_offset < length)
3252      {      {
3253      tb = ((USPTR)subject)[start_offset] & 0xc0;      if (offsetcount >= 2)
3254      if (tb == 0x80) return PCRE_ERROR_BADUTF8_OFFSET;        {
3255          offsets[0] = erroroffset;
3256          offsets[1] = errorcode;
3257          }
3258    #if defined COMPILE_PCRE8
3259        return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0) ?
3261    #elif defined COMPILE_PCRE16
3262        return (errorcode <= PCRE_UTF16_ERR1 && (options & PCRE_PARTIAL_HARD) != 0) ?
3264    #elif defined COMPILE_PCRE32
3266    #endif
3267      }      }
3268    #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
3269      if (start_offset > 0 && start_offset < length &&
3270            NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
3272    #endif
3273    }    }
3274  #endif  #endif
3275
# Line 2979  if (utf8 && (options & PCRE_NO_UTF8_CHEC Line 3277  if (utf8 && (options & PCRE_NO_UTF8_CHEC
3277  is a feature that makes it possible to save compiled regex and re-use them  is a feature that makes it possible to save compiled regex and re-use them
3278  in other programs later. */  in other programs later. */
3279
3280  if (md->tables == NULL) md->tables = _pcre_default_tables;  if (md->tables == NULL) md->tables = PRIV(default_tables);
3281
3282  /* The lower casing table and the "must be at the start of a line" flag are  /* The "must be at the start of a line" flags are used in a loop when finding
3283  used in a loop when finding where to start. */  where to start. */
3284
lcc = md->tables + lcc_offset;
3285  startline = (re->flags & PCRE_STARTLINE) != 0;  startline = (re->flags & PCRE_STARTLINE) != 0;
3286  firstline = (re->options & PCRE_FIRSTLINE) != 0;  firstline = (re->options & PCRE_FIRSTLINE) != 0;
3287
# Line 2998  if (!anchored) Line 3295  if (!anchored)
3295    {    {
3296    if ((re->flags & PCRE_FIRSTSET) != 0)    if ((re->flags & PCRE_FIRSTSET) != 0)
3297      {      {
3298      first_byte = re->first_byte & 255;      has_first_char = TRUE;
3299      if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)      first_char = first_char2 = (pcre_uchar)(re->first_char);
3300        first_byte = lcc[first_byte];      if ((re->flags & PCRE_FCH_CASELESS) != 0)
3301          {
3302          first_char2 = TABLE_GET(first_char, md->tables + fcc_offset, first_char);
3303    #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
3304          if (utf && first_char > 127)
3305            first_char2 = UCD_OTHERCASE(first_char);
3306    #endif
3307          }
3308      }      }
3309    else    else
3310      {      {
# Line 3015  character" set. */ Line 3319  character" set. */
3319
3320  if ((re->flags & PCRE_REQCHSET) != 0)  if ((re->flags & PCRE_REQCHSET) != 0)
3321    {    {
3322    req_byte = re->req_byte & 255;    has_req_char = TRUE;
3323    req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;    req_char = req_char2 = (pcre_uchar)(re->req_char);
3324    req_byte2 = (md->tables + fcc_offset)[req_byte];  /* case flipped */    if ((re->flags & PCRE_RCH_CASELESS) != 0)
3325        {
3326        req_char2 = TABLE_GET(req_char, md->tables + fcc_offset, req_char);
3327    #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
3328        if (utf && req_char > 127)
3329          req_char2 = UCD_OTHERCASE(req_char);
3330    #endif
3331        }
3332    }    }
3333
3334  /* Call the main matching function, looping for a non-anchored regex after a  /* Call the main matching function, looping for a non-anchored regex after a
# Line 3030  for (;;) Line 3341  for (;;)
3341
3342    if ((options & PCRE_DFA_RESTART) == 0)    if ((options & PCRE_DFA_RESTART) == 0)
3343      {      {
3344      const uschar *save_end_subject = end_subject;      const pcre_uchar *save_end_subject = end_subject;
3345
3346      /* If firstline is TRUE, the start of the match is constrained to the first      /* If firstline is TRUE, the start of the match is constrained to the first
3347      line of a multiline string. Implement this by temporarily adjusting      line of a multiline string. Implement this by temporarily adjusting
# Line 3039  for (;;) Line 3350  for (;;)
3350
3351      if (firstline)      if (firstline)
3352        {        {
3353        USPTR t = current_subject;        PCRE_PUCHAR t = current_subject;
3354  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3355        if (utf8)        if (utf)
3356          {          {
3357          while (t < md->end_subject && !IS_NEWLINE(t))          while (t < md->end_subject && !IS_NEWLINE(t))
3358            {            {
3359            t++;            t++;
3360            while (t < end_subject && (*t & 0xc0) == 0x80) t++;            ACROSSCHAR(t < end_subject, *t, t++);
3361            }            }
3362          }          }
3363        else        else
# Line 3063  for (;;) Line 3374  for (;;)
3374
3375      if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)      if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
3376        {        {
3377        /* Advance to a known first byte. */        /* Advance to a known first char. */
3378
3379        if (first_byte >= 0)        if (has_first_char)
3380          {          {
3381          if (first_byte_caseless)          if (first_char != first_char2)
3382              {
3383              pcre_uchar csc;
3384            while (current_subject < end_subject &&            while (current_subject < end_subject &&
3385                   lcc[*current_subject] != first_byte)                   (csc = RAWUCHARTEST(current_subject)) != first_char && csc != first_char2)
3386              current_subject++;              current_subject++;
3387              }
3388          else          else
3389            while (current_subject < end_subject &&            while (current_subject < end_subject &&
3390                   *current_subject != first_byte)                   RAWUCHARTEST(current_subject) != first_char)
3391              current_subject++;              current_subject++;
3392          }          }
3393
# Line 3083  for (;;) Line 3397  for (;;)
3397          {          {
3398          if (current_subject > md->start_subject + start_offset)          if (current_subject > md->start_subject + start_offset)
3399            {            {
3400  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF
3401            if (utf8)            if (utf)
3402              {              {
3403              while (current_subject < end_subject &&              while (current_subject < end_subject &&
3404                     !WAS_NEWLINE(current_subject))                     !WAS_NEWLINE(current_subject))
3405                {                {
3406                current_subject++;                current_subject++;
3407                while(current_subject < end_subject &&                ACROSSCHAR(current_subject < end_subject, *current_subject,
3408                      (*current_subject & 0xc0) == 0x80)                  current_subject++);
current_subject++;
3409                }                }
3410              }              }
3411            else            else
# Line 3104  for (;;) Line 3417  for (;;)
3417            ANYCRLF, and we are now at a LF, advance the match position by one            ANYCRLF, and we are now at a LF, advance the match position by one
3418            more character. */            more character. */
3419
3420            if (current_subject[-1] == CHAR_CR &&            if (RAWUCHARTEST(current_subject - 1) == CHAR_CR &&
3421                 (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&                 (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
3422                 current_subject < end_subject &&                 current_subject < end_subject &&
3423                 *current_subject == CHAR_NL)                 RAWUCHARTEST(current_subject) == CHAR_NL)
3424              current_subject++;              current_subject++;
3425            }            }
3426          }          }
# Line 3118  for (;;) Line 3431  for (;;)
3431          {          {
3432          while (current_subject < end_subject)          while (current_subject < end_subject)
3433            {            {
3434            register unsigned int c = *current_subject;            register pcre_uint32 c = RAWUCHARTEST(current_subject);
3435    #ifndef COMPILE_PCRE8
3436              if (c > 255) c = 255;
3437    #endif
3438            if ((start_bits[c/8] & (1 << (c&7))) == 0)            if ((start_bits[c/8] & (1 << (c&7))) == 0)
3439              {              {
3440              current_subject++;              current_subject++;
3441  #ifdef SUPPORT_UTF8  #if defined SUPPORT_UTF && defined COMPILE_PCRE8
3442              if (utf8)              /* In non 8-bit mode, the iteration will stop for
3443                while(current_subject < end_subject &&              characters > 255 at the beginning or not stop at all. */
3444                      (*current_subject & 0xc0) == 0x80) current_subject++;              if (utf)
3445                  ACROSSCHAR(current_subject < end_subject, *current_subject,
3446                    current_subject++);
3447  #endif  #endif
3448              }              }
3449            else break;            else break;
# Line 3141  for (;;) Line 3459  for (;;)
3459      disabling is explicitly requested (and of course, by the test above, this      disabling is explicitly requested (and of course, by the test above, this
3460      code is not obeyed when restarting after a partial match). */      code is not obeyed when restarting after a partial match). */
3461
3462      if ((options & PCRE_NO_START_OPTIMIZE) == 0 &&      if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 &&
3463          (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0)          (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0)
3464        {        {
3465        /* If the pattern was studied, a minimum subject length may be set. This        /* If the pattern was studied, a minimum subject length may be set. This
# Line 3153  for (;;) Line 3471  for (;;)
3471            (pcre_uint32)(end_subject - current_subject) < study->minlength)            (pcre_uint32)(end_subject - current_subject) < study->minlength)
3472          return PCRE_ERROR_NOMATCH;          return PCRE_ERROR_NOMATCH;
3473
3474        /* If req_byte is set, we know that that character must appear in the        /* If req_char is set, we know that that character must appear in the
3475        subject for the match to succeed. If the first character is set, req_byte        subject for the match to succeed. If the first character is set, req_char
3476        must be later in the subject; otherwise the test starts at the match        must be later in the subject; otherwise the test starts at the match
3477        point. This optimization can save a huge amount of work in patterns with        point. This optimization can save a huge amount of work in patterns with
3478        nested unlimited repeats that aren't going to match. Writing separate        nested unlimited repeats that aren't going to match. Writing separate
# Line 3166  for (;;) Line 3484  for (;;)
3484        patterns. This showed up when somebody was matching /^C/ on a 32-megabyte        patterns. This showed up when somebody was matching /^C/ on a 32-megabyte
3485        string... so we don't do this when the string is sufficiently long. */        string... so we don't do this when the string is sufficiently long. */
3486
3487        if (req_byte >= 0 && end_subject - current_subject < REQ_BYTE_MAX)        if (has_req_char && end_subject - current_subject < REQ_BYTE_MAX)
3488          {          {
3489          register const uschar *p = current_subject + ((first_byte >= 0)? 1 : 0);          register PCRE_PUCHAR p = current_subject + (has_first_char? 1:0);
3490
3491          /* We don't need to repeat the search if we haven't yet reached the          /* We don't need to repeat the search if we haven't yet reached the
3492          place we found it at last time. */          place we found it at last time. */
3493
3494          if (p > req_byte_ptr)          if (p > req_char_ptr)
3495            {            {
3496            if (req_byte_caseless)            if (req_char != req_char2)
3497              {              {
3498              while (p < end_subject)              while (p < end_subject)
3499                {                {
3500                register int pp = *p++;                register pcre_uint32 pp = RAWUCHARINCTEST(p);
3501                if (pp == req_byte || pp == req_byte2) { p--; break; }                if (pp == req_char || pp == req_char2) { p--; break; }
3502                }                }
3503              }              }
3504            else            else
3505              {              {
3506              while (p < end_subject)              while (p < end_subject)
3507                {                {
3508                if (*p++ == req_byte) { p--; break; }                if (RAWUCHARINCTEST(p) == req_char) { p--; break; }
3509                }                }
3510              }              }
3511
# Line 3200  for (;;) Line 3518  for (;;)
3518            found it, so that we don't search again next time round the loop if            found it, so that we don't search again next time round the loop if
3519            the start hasn't passed this character yet. */            the start hasn't passed this character yet. */
3520
3521            req_byte_ptr = p;            req_char_ptr = p;
3522            }            }
3523          }          }
3524        }        }
# Line 3209  for (;;) Line 3527  for (;;)
3527    /* OK, now we can do the business */    /* OK, now we can do the business */
3528
3529    md->start_used_ptr = current_subject;    md->start_used_ptr = current_subject;
3530      md->recursive = NULL;
3531
3532    rc = internal_dfa_exec(    rc = internal_dfa_exec(
3533      md,                                /* fixed match data */      md,                                /* fixed match data */
# Line 3219  for (;;) Line 3538  for (;;)
3538      offsetcount,                       /* size of same */      offsetcount,                       /* size of same */
3539      workspace,                         /* workspace vector */      workspace,                         /* workspace vector */
3540      wscount,                           /* size of same */      wscount,                           /* size of same */
3541      re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL), /* ims flags */      0);                                /* function recurse level */
0,                                 /* function recurse level */
0);                                /* regex recurse level */
3542
3543    /* Anything other than "no match" means we are done, always; otherwise, carry    /* Anything other than "no match" means we are done, always; otherwise, carry
3544    on only if not anchored. */    on only if not anchored. */
# Line 3233  for (;;) Line 3550  for (;;)
3550
3551    if (firstline && IS_NEWLINE(current_subject)) break;    if (firstline && IS_NEWLINE(current_subject)) break;
3552    current_subject++;    current_subject++;
3553    if (utf8)  #ifdef SUPPORT_UTF
3554      if (utf)
3555      {      {
3556      while (current_subject < end_subject && (*current_subject & 0xc0) == 0x80)      ACROSSCHAR(current_subject < end_subject, *current_subject,
3557        current_subject++;        current_subject++);
3558      }      }
3559    #endif
3560    if (current_subject > end_subject) break;    if (current_subject > end_subject) break;
3561
3562    /* If we have just passed a CR and we are now at a LF, and the pattern does    /* If we have just passed a CR and we are now at a LF, and the pattern does
3563    not contain any explicit matches for \r or \n, and the newline option is CRLF    not contain any explicit matches for \r or \n, and the newline option is CRLF
3564    or ANY or ANYCRLF, advance the match position by one more character. */    or ANY or ANYCRLF, advance the match position by one more character. */
3565
3566    if (current_subject[-1] == CHAR_CR &&    if (RAWUCHARTEST(current_subject - 1) == CHAR_CR &&
3567        current_subject < end_subject &&        current_subject < end_subject &&
3568        *current_subject == CHAR_NL &&        RAWUCHARTEST(current_subject) == CHAR_NL &&
3569        (re->flags & PCRE_HASCRORLF) == 0 &&        (re->flags & PCRE_HASCRORLF) == 0 &&
3570          (md->nltype == NLTYPE_ANY ||          (md->nltype == NLTYPE_ANY ||
3571           md->nltype == NLTYPE_ANYCRLF ||           md->nltype == NLTYPE_ANYCRLF ||

Legend:
 Removed from v.579 changed lines Added in v.1100