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

Diff of /code/trunk/pcre_dfa_exec.c

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

revision 530 by ph10, Tue Jun 1 13:42:06 2010 UTC revision 728 by ph10, Mon Oct 10 16:01:03 2011 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-2011 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 121  static const uschar coptable[] = { Line 121  static const uschar coptable[] = {
121    0, 0,                          /* \P, \p                                 */    0, 0,                          /* \P, \p                                 */
122    0, 0, 0, 0, 0,                 /* \R, \H, \h, \V, \v                     */    0, 0, 0, 0, 0,                 /* \R, \H, \h, \V, \v                     */
123    0,                             /* \X                                     */    0,                             /* \X                                     */
124    0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, $                      */    0, 0, 0, 0, 0, 0,              /* \Z, \z, ^, ^M, $, $M                   */
125    1,                             /* Char                                   */    1,                             /* Char                                   */
126    1,                             /* Charnc                                 */    1,                             /* Chari                                  */
127    1,                             /* not                                    */    1,                             /* not                                    */
128      1,                             /* noti                                   */
129    /* Positive single-char repeats                                          */    /* Positive single-char repeats                                          */
130    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
131    3, 3, 3,                       /* upto, minupto, exact                   */    3, 3, 3,                       /* upto, minupto, exact                   */
132    1, 1, 1, 3,                    /* *+, ++, ?+, upto+                      */    1, 1, 1, 3,                    /* *+, ++, ?+, upto+                      */
133      1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */
134      3, 3, 3,                       /* upto I, minupto I, exact I             */
135      1, 1, 1, 3,                    /* *+I, ++I, ?+I, upto+I                  */
136    /* Negative single-char repeats - only for chars < 256                   */    /* Negative single-char repeats - only for chars < 256                   */
137    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
138    3, 3, 3,                       /* NOT upto, minupto, exact               */    3, 3, 3,                       /* NOT upto, minupto, exact               */
139    1, 1, 1, 3,                    /* NOT *+, ++, ?+, updo+                  */    1, 1, 1, 3,                    /* NOT *+, ++, ?+, upto+                  */
140      1, 1, 1, 1, 1, 1,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */
141      3, 3, 3,                       /* NOT upto I, minupto I, exact I         */
142      1, 1, 1, 3,                    /* NOT *+I, ++I, ?+I, upto+I              */
143    /* Positive type repeats                                                 */    /* Positive type repeats                                                 */
144    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
145    3, 3, 3,                       /* Type upto, minupto, exact              */    3, 3, 3,                       /* Type upto, minupto, exact              */
# Line 144  static const uschar coptable[] = { Line 151  static const uschar coptable[] = {
151    0,                             /* NCLASS                                 */    0,                             /* NCLASS                                 */
152    0,                             /* XCLASS - variable length               */    0,                             /* XCLASS - variable length               */
153    0,                             /* REF                                    */    0,                             /* REF                                    */
154      0,                             /* REFI                                   */
155    0,                             /* RECURSE                                */    0,                             /* RECURSE                                */
156    0,                             /* CALLOUT                                */    0,                             /* CALLOUT                                */
157    0,                             /* Alt                                    */    0,                             /* Alt                                    */
158    0,                             /* Ket                                    */    0,                             /* Ket                                    */
159    0,                             /* KetRmax                                */    0,                             /* KetRmax                                */
160    0,                             /* KetRmin                                */    0,                             /* KetRmin                                */
161      0,                             /* KetRpos                                */
162      0,                             /* Reverse                                */
163    0,                             /* Assert                                 */    0,                             /* Assert                                 */
164    0,                             /* Assert not                             */    0,                             /* Assert not                             */
165    0,                             /* Assert behind                          */    0,                             /* Assert behind                          */
166    0,                             /* Assert behind not                      */    0,                             /* Assert behind not                      */
167    0,                             /* Reverse                                */    0, 0,                          /* ONCE, ONCE_NC                          */
168    0, 0, 0, 0,                    /* ONCE, BRA, CBRA, COND                  */    0, 0, 0, 0, 0,                 /* BRA, BRAPOS, CBRA, CBRAPOS, COND       */
169    0, 0, 0,                       /* SBRA, SCBRA, SCOND                     */    0, 0, 0, 0, 0,                 /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND  */
170    0, 0,                          /* CREF, NCREF                            */    0, 0,                          /* CREF, NCREF                            */
171    0, 0,                          /* RREF, NRREF                            */    0, 0,                          /* RREF, NRREF                            */
172    0,                             /* DEF                                    */    0,                             /* DEF                                    */
173    0, 0,                          /* BRAZERO, BRAMINZERO                    */    0, 0, 0,                       /* BRAZERO, BRAMINZERO, BRAPOSZERO        */
174    0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG,                */    0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG                 */
175    0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG,        */    0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG         */
176    0, 0, 0, 0, 0                  /* COMMIT, FAIL, ACCEPT, CLOSE, SKIPZERO  */    0, 0, 0, 0,                    /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT    */
177      0, 0                           /* CLOSE, SKIPZERO  */
178  };  };
179    
180  /* 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 179  static const uschar poptable[] = { Line 190  static const uschar poptable[] = {
190    1, 1,                          /* \P, \p                                 */    1, 1,                          /* \P, \p                                 */
191    1, 1, 1, 1, 1,                 /* \R, \H, \h, \V, \v                     */    1, 1, 1, 1, 1,                 /* \R, \H, \h, \V, \v                     */
192    1,                             /* \X                                     */    1,                             /* \X                                     */
193    0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, $                      */    0, 0, 0, 0, 0, 0,              /* \Z, \z, ^, ^M, $, $M                   */
194    1,                             /* Char                                   */    1,                             /* Char                                   */
195    1,                             /* Charnc                                 */    1,                             /* Chari                                  */
196    1,                             /* not                                    */    1,                             /* not                                    */
197      1,                             /* noti                                   */
198    /* Positive single-char repeats                                          */    /* Positive single-char repeats                                          */
199    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
200    1, 1, 1,                       /* upto, minupto, exact                   */    1, 1, 1,                       /* upto, minupto, exact                   */
201    1, 1, 1, 1,                    /* *+, ++, ?+, upto+                      */    1, 1, 1, 1,                    /* *+, ++, ?+, upto+                      */
202      1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */
203      1, 1, 1,                       /* upto I, minupto I, exact I             */
204      1, 1, 1, 1,                    /* *+I, ++I, ?+I, upto+I                  */
205    /* Negative single-char repeats - only for chars < 256                   */    /* Negative single-char repeats - only for chars < 256                   */
206    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
207    1, 1, 1,                       /* NOT upto, minupto, exact               */    1, 1, 1,                       /* NOT upto, minupto, exact               */
208    1, 1, 1, 1,                    /* NOT *+, ++, ?+, upto+                  */    1, 1, 1, 1,                    /* NOT *+, ++, ?+, upto+                  */
209      1, 1, 1, 1, 1, 1,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */
210      1, 1, 1,                       /* NOT upto I, minupto I, exact I         */
211      1, 1, 1, 1,                    /* NOT *+I, ++I, ?+I, upto+I              */
212    /* Positive type repeats                                                 */    /* Positive type repeats                                                 */
213    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
214    1, 1, 1,                       /* Type upto, minupto, exact              */    1, 1, 1,                       /* Type upto, minupto, exact              */
# Line 202  static const uschar poptable[] = { Line 220  static const uschar poptable[] = {
220    1,                             /* NCLASS                                 */    1,                             /* NCLASS                                 */
221    1,                             /* XCLASS - variable length               */    1,                             /* XCLASS - variable length               */
222    0,                             /* REF                                    */    0,                             /* REF                                    */
223      0,                             /* REFI                                   */
224    0,                             /* RECURSE                                */    0,                             /* RECURSE                                */
225    0,                             /* CALLOUT                                */    0,                             /* CALLOUT                                */
226    0,                             /* Alt                                    */    0,                             /* Alt                                    */
227    0,                             /* Ket                                    */    0,                             /* Ket                                    */
228    0,                             /* KetRmax                                */    0,                             /* KetRmax                                */
229    0,                             /* KetRmin                                */    0,                             /* KetRmin                                */
230      0,                             /* KetRpos                                */
231      0,                             /* Reverse                                */
232    0,                             /* Assert                                 */    0,                             /* Assert                                 */
233    0,                             /* Assert not                             */    0,                             /* Assert not                             */
234    0,                             /* Assert behind                          */    0,                             /* Assert behind                          */
235    0,                             /* Assert behind not                      */    0,                             /* Assert behind not                      */
236    0,                             /* Reverse                                */    0, 0,                          /* ONCE, ONCE_NC                          */
237    0, 0, 0, 0,                    /* ONCE, BRA, CBRA, COND                  */    0, 0, 0, 0, 0,                 /* BRA, BRAPOS, CBRA, CBRAPOS, COND       */
238    0, 0, 0,                       /* SBRA, SCBRA, SCOND                     */    0, 0, 0, 0, 0,                 /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND  */
239    0, 0,                          /* CREF, NCREF                            */    0, 0,                          /* CREF, NCREF                            */
240    0, 0,                          /* RREF, NRREF                            */    0, 0,                          /* RREF, NRREF                            */
241    0,                             /* DEF                                    */    0,                             /* DEF                                    */
242    0, 0,                          /* BRAZERO, BRAMINZERO                    */    0, 0, 0,                       /* BRAZERO, BRAMINZERO, BRAPOSZERO        */
243    0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG,                */    0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG                 */
244    0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG,        */    0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG         */
245    0, 0, 0, 0, 0                  /* COMMIT, FAIL, ACCEPT, CLOSE, SKIPZERO  */    0, 0, 0, 0,                    /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT    */
246      0, 0                           /* CLOSE, SKIPZERO                        */
247  };  };
248    
249  /* 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,
# Line 252  these structures in, is a vector of ints Line 274  these structures in, is a vector of ints
274  typedef struct stateblock {  typedef struct stateblock {
275    int offset;                     /* Offset to opcode */    int offset;                     /* Offset to opcode */
276    int count;                      /* Count for repeats */    int count;                      /* Count for repeats */
   int ims;                        /* ims flag bits */  
277    int data;                       /* Some use extra data */    int data;                       /* Some use extra data */
278  } stateblock;  } stateblock;
279    
# Line 308  Arguments: Line 329  Arguments:
329    offsetcount       size of same    offsetcount       size of same
330    workspace         vector of workspace    workspace         vector of workspace
331    wscount           size of same    wscount           size of same
   ims               the current ims flags  
332    rlevel            function call recursion level    rlevel            function call recursion level
   recursing         regex recursive call level  
333    
334  Returns:            > 0 => number of match offset pairs placed in offsets  Returns:            > 0 => number of match offset pairs placed in offsets
335                      = 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 344  for the current character, one for the f
344      { \      { \
345      next_active_state->offset = (x); \      next_active_state->offset = (x); \
346      next_active_state->count  = (y); \      next_active_state->count  = (y); \
     next_active_state->ims    = ims; \  
347      next_active_state++; \      next_active_state++; \
348      DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \      DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
349      } \      } \
# Line 336  for the current character, one for the f Line 354  for the current character, one for the f
354      { \      { \
355      next_active_state->offset = (x); \      next_active_state->offset = (x); \
356      next_active_state->count  = (y); \      next_active_state->count  = (y); \
     next_active_state->ims    = ims; \  
357      next_active_state->data   = (z); \      next_active_state->data   = (z); \
358      next_active_state++; \      next_active_state++; \
359      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 365  for the current character, one for the f
365      { \      { \
366      next_new_state->offset = (x); \      next_new_state->offset = (x); \
367      next_new_state->count  = (y); \      next_new_state->count  = (y); \
     next_new_state->ims    = ims; \  
368      next_new_state++; \      next_new_state++; \
369      DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \      DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
370      } \      } \
# Line 359  for the current character, one for the f Line 375  for the current character, one for the f
375      { \      { \
376      next_new_state->offset = (x); \      next_new_state->offset = (x); \
377      next_new_state->count  = (y); \      next_new_state->count  = (y); \
     next_new_state->ims    = ims; \  
378      next_new_state->data   = (z); \      next_new_state->data   = (z); \
379      next_new_state++; \      next_new_state++; \
380      DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \      DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \
# Line 378  internal_dfa_exec( Line 393  internal_dfa_exec(
393    int offsetcount,    int offsetcount,
394    int *workspace,    int *workspace,
395    int wscount,    int wscount,
396    int ims,    int  rlevel)
   int  rlevel,  
   int  recursing)  
397  {  {
398  stateblock *active_states, *new_states, *temp_states;  stateblock *active_states, *new_states, *temp_states;
399  stateblock *next_active_state, *next_new_state;  stateblock *next_active_state, *next_new_state;
# Line 389  const uschar *ctypes, *lcc, *fcc; Line 402  const uschar *ctypes, *lcc, *fcc;
402  const uschar *ptr;  const uschar *ptr;
403  const uschar *end_code, *first_op;  const uschar *end_code, *first_op;
404    
405    dfa_recursion_info new_recursive;
406    
407  int active_count, new_count, match_count;  int active_count, new_count, match_count;
408    
409  /* 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
# Line 412  wscount = (wscount - (wscount % (INTS_PE Line 427  wscount = (wscount - (wscount % (INTS_PE
427            (2 * INTS_PER_STATEBLOCK);            (2 * INTS_PER_STATEBLOCK);
428    
429  DPRINTF(("\n%.*s---------------------\n"  DPRINTF(("\n%.*s---------------------\n"
430    "%.*sCall to internal_dfa_exec f=%d r=%d\n",    "%.*sCall to internal_dfa_exec f=%d\n",
431    rlevel*2-2, SP, rlevel*2-2, SP, rlevel, recursing));    rlevel*2-2, SP, rlevel*2-2, SP, rlevel));
432    
433  ctypes = md->tables + ctypes_offset;  ctypes = md->tables + ctypes_offset;
434  lcc = md->tables + lcc_offset;  lcc = md->tables + lcc_offset;
# Line 426  next_new_state = new_states = active_sta Line 441  next_new_state = new_states = active_sta
441  new_count = 0;  new_count = 0;
442    
443  first_op = this_start_code + 1 + LINK_SIZE +  first_op = this_start_code + 1 + LINK_SIZE +
444    ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA)? 2:0);    ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||
445        *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)? 2:0);
446    
447  /* 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
448  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 525  else Line 541  else
541    else    else
542      {      {
543      int length = 1 + LINK_SIZE +      int length = 1 + LINK_SIZE +
544        ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA)? 2:0);        ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||
545            *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)?
546            2:0);
547      do      do
548        {        {
549        ADD_NEW((int)(end_code - start_code + length), 0);        ADD_NEW((int)(end_code - start_code + length), 0);
# Line 605  for (;;) Line 623  for (;;)
623    for (i = 0; i < active_count; i++)    for (i = 0; i < active_count; i++)
624      {      {
625      stateblock *current_state = active_states + i;      stateblock *current_state = active_states + i;
626        BOOL caseless = FALSE;
627      const uschar *code;      const uschar *code;
628      int state_offset = current_state->offset;      int state_offset = current_state->offset;
629      int count, codevalue, rrc;      int count, codevalue, rrc;
# Line 616  for (;;) Line 635  for (;;)
635          else printf("0x%02x\n", c);          else printf("0x%02x\n", c);
636  #endif  #endif
637    
     /* This variable is referred to implicity in the ADD_xxx macros. */  
   
     ims = current_state->ims;  
   
638      /* 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
639      (negated) state until the number of characters in the data field have      (negated) state until the number of characters in the data field have
640      been skipped". */      been skipped". */
# Line 725  for (;;) Line 740  for (;;)
740    
741  /* ========================================================================== */  /* ========================================================================== */
742        /* 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
743        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
744          state. Note that KETRPOS will always be encountered at the end of the
745          subpattern, because the possessive subpattern repeats are always handled
746          using recursive calls. Thus, it never adds any new states.
747    
748          At the end of the (sub)pattern, unless we have an empty string and
749        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
750        start of the subject, save the match data, shifting up all previous        start of the subject, save the match data, shifting up all previous
751        matches so we always have the longest first. */        matches so we always have the longest first. */
# Line 733  for (;;) Line 753  for (;;)
753        case OP_KET:        case OP_KET:
754        case OP_KETRMIN:        case OP_KETRMIN:
755        case OP_KETRMAX:        case OP_KETRMAX:
756          case OP_KETRPOS:
757        if (code != end_code)        if (code != end_code)
758          {          {
759          ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0);          ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0);
# Line 749  for (;;) Line 770  for (;;)
770                  current_subject > start_subject + md->start_offset)))                  current_subject > start_subject + md->start_offset)))
771            {            {
772            if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;            if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;
773              else if (match_count > 0 && ++match_count * 2 >= offsetcount)              else if (match_count > 0 && ++match_count * 2 > offsetcount)
774                match_count = 0;                match_count = 0;
775            count = ((match_count == 0)? offsetcount : match_count * 2) - 2;            count = ((match_count == 0)? offsetcount : match_count * 2) - 2;
776            if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));            if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));
# Line 822  for (;;) Line 843  for (;;)
843    
844        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
845        case OP_CIRC:        case OP_CIRC:
846        if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||        if (ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0)
           ((ims & PCRE_MULTILINE) != 0 &&  
             ptr != end_subject &&  
             WAS_NEWLINE(ptr)))  
847          { ADD_ACTIVE(state_offset + 1, 0); }          { ADD_ACTIVE(state_offset + 1, 0); }
848        break;        break;
849    
850        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
851        case OP_EOD:        case OP_CIRCM:
852        if (ptr >= end_subject) { ADD_ACTIVE(state_offset + 1, 0); }        if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||
853              (ptr != end_subject && WAS_NEWLINE(ptr)))
854            { ADD_ACTIVE(state_offset + 1, 0); }
855        break;        break;
856    
857        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
858        case OP_OPT:        case OP_EOD:
859        ims = code[1];        if (ptr >= end_subject)
860        ADD_ACTIVE(state_offset + 2, 0);          {
861            if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
862              could_continue = TRUE;
863            else { ADD_ACTIVE(state_offset + 1, 0); }
864            }
865        break;        break;
866    
867        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
# Line 871  for (;;) Line 895  for (;;)
895    
896        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
897        case OP_EODN:        case OP_EODN:
898        if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen))        if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
899            could_continue = TRUE;
900          else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen))
901          { ADD_ACTIVE(state_offset + 1, 0); }          { ADD_ACTIVE(state_offset + 1, 0); }
902        break;        break;
903    
# Line 879  for (;;) Line 905  for (;;)
905        case OP_DOLL:        case OP_DOLL:
906        if ((md->moptions & PCRE_NOTEOL) == 0)        if ((md->moptions & PCRE_NOTEOL) == 0)
907          {          {
908          if (clen == 0 ||          if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
909              could_continue = TRUE;
910            else if (clen == 0 ||
911              ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&              ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&
912                 ((ims & PCRE_MULTILINE) != 0 || ptr == end_subject - md->nllen)                 (ptr == end_subject - md->nllen)
913              ))              ))
914            { ADD_ACTIVE(state_offset + 1, 0); }            { ADD_ACTIVE(state_offset + 1, 0); }
915          }          }
916        else if ((ims & PCRE_MULTILINE) != 0 && IS_NEWLINE(ptr))        break;
917    
918          /*-----------------------------------------------------------------*/
919          case OP_DOLLM:
920          if ((md->moptions & PCRE_NOTEOL) == 0)
921            {
922            if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
923              could_continue = TRUE;
924            else if (clen == 0 ||
925                ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))
926              { ADD_ACTIVE(state_offset + 1, 0); }
927            }
928          else if (IS_NEWLINE(ptr))
929          { ADD_ACTIVE(state_offset + 1, 0); }          { ADD_ACTIVE(state_offset + 1, 0); }
930        break;        break;
931    
# Line 922  for (;;) Line 962  for (;;)
962            if (utf8) BACKCHAR(temp);            if (utf8) BACKCHAR(temp);
963  #endif  #endif
964            GETCHARTEST(d, temp);            GETCHARTEST(d, temp);
965  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
966            if ((md->poptions & PCRE_UCP) != 0)            if ((md->poptions & PCRE_UCP) != 0)
967              {              {
968              if (d == '_') left_word = TRUE; else              if (d == '_') left_word = TRUE; else
969                {                {
970                int cat = UCD_CATEGORY(d);                int cat = UCD_CATEGORY(d);
971                left_word = (cat == ucp_L || cat == ucp_N);                left_word = (cat == ucp_L || cat == ucp_N);
972                }                }
973              }              }
974            else            else
975  #endif  #endif
976            left_word = d < 256 && (ctypes[d] & ctype_word) != 0;            left_word = d < 256 && (ctypes[d] & ctype_word) != 0;
977            }            }
978          else left_word = FALSE;          else left_word = FALSE;
979    
980          if (clen > 0)          if (clen > 0)
981            {            {
982  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
983            if ((md->poptions & PCRE_UCP) != 0)            if ((md->poptions & PCRE_UCP) != 0)
984              {              {
985              if (c == '_') right_word = TRUE; else              if (c == '_') right_word = TRUE; else
986                {                {
987                int cat = UCD_CATEGORY(c);                int cat = UCD_CATEGORY(c);
988                right_word = (cat == ucp_L || cat == ucp_N);                right_word = (cat == ucp_L || cat == ucp_N);
989                }                }
990              }              }
991            else            else
992  #endif  #endif
993            right_word = c < 256 && (ctypes[c] & ctype_word) != 0;            right_word = c < 256 && (ctypes[c] & ctype_word) != 0;
994            }            }
995          else right_word = FALSE;          else right_word = FALSE;
996    
997          if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))          if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))
# Line 979  for (;;) Line 1019  for (;;)
1019            break;            break;
1020    
1021            case PT_LAMP:            case PT_LAMP:
1022            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
1023                 prop->chartype == ucp_Lt;                 prop->chartype == ucp_Lt;
1024            break;            break;
1025    
# Line 994  for (;;) Line 1034  for (;;)
1034            case PT_SC:            case PT_SC:
1035            OK = prop->script == code[2];            OK = prop->script == code[2];
1036            break;            break;
1037    
1038            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1039    
1040            case PT_ALNUM:            case PT_ALNUM:
1041            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
1042                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 _pcre_ucp_gentype[prop->chartype] == ucp_N;
1043            break;            break;
1044    
1045            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1046            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
1047                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1048            break;            break;
1049    
1050            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1051            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
1052                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1053                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1054            break;            break;
1055    
1056            case PT_WORD:            case PT_WORD:
1057            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
1058                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||
1059                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1060            break;            break;
1061    
1062            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1063    
# Line 1173  for (;;) Line 1213  for (;;)
1213            break;            break;
1214    
1215            case PT_LAMP:            case PT_LAMP:
1216            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
1217              prop->chartype == ucp_Lt;              prop->chartype == ucp_Lt;
1218            break;            break;
1219    
# Line 1190  for (;;) Line 1230  for (;;)
1230            break;            break;
1231    
1232            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1233    
1234            case PT_ALNUM:            case PT_ALNUM:
1235            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
1236                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 _pcre_ucp_gentype[prop->chartype] == ucp_N;
1237            break;            break;
1238    
1239            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1240            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
1241                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1242            break;            break;
1243    
1244            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1245            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
1246                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1247                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1248            break;            break;
1249    
1250            case PT_WORD:            case PT_WORD:
1251            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
1252                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||
1253                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1254            break;            break;
1255    
1256            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1257    
# Line 1420  for (;;) Line 1460  for (;;)
1460            break;            break;
1461    
1462            case PT_LAMP:            case PT_LAMP:
1463            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
1464              prop->chartype == ucp_Lt;              prop->chartype == ucp_Lt;
1465            break;            break;
1466    
# Line 1435  for (;;) Line 1475  for (;;)
1475            case PT_SC:            case PT_SC:
1476            OK = prop->script == code[3];            OK = prop->script == code[3];
1477            break;            break;
1478    
1479            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1480    
1481            case PT_ALNUM:            case PT_ALNUM:
1482            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
1483                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 _pcre_ucp_gentype[prop->chartype] == ucp_N;
1484            break;            break;
1485    
1486            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1487            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
1488                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1489            break;            break;
1490    
1491            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1492            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
1493                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1494                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1495            break;            break;
1496    
1497            case PT_WORD:            case PT_WORD:
1498            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
1499                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||
1500                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1501            break;            break;
1502    
1503            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1504    
# Line 1692  for (;;) Line 1732  for (;;)
1732            break;            break;
1733    
1734            case PT_LAMP:            case PT_LAMP:
1735            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
1736              prop->chartype == ucp_Lt;              prop->chartype == ucp_Lt;
1737            break;            break;
1738    
# Line 1707  for (;;) Line 1747  for (;;)
1747            case PT_SC:            case PT_SC:
1748            OK = prop->script == code[5];            OK = prop->script == code[5];
1749            break;            break;
1750    
1751            /* These are specials for combination cases. */            /* These are specials for combination cases. */
1752    
1753            case PT_ALNUM:            case PT_ALNUM:
1754            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
1755                 _pcre_ucp_gentype[prop->chartype] == ucp_N;                 _pcre_ucp_gentype[prop->chartype] == ucp_N;
1756            break;            break;
1757    
1758            case PT_SPACE:    /* Perl space */            case PT_SPACE:    /* Perl space */
1759            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
1760                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;                 c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
1761            break;            break;
1762    
1763            case PT_PXSPACE:  /* POSIX space */            case PT_PXSPACE:  /* POSIX space */
1764            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
1765                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||                 c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
1766                 c == CHAR_FF || c == CHAR_CR;                 c == CHAR_FF || c == CHAR_CR;
1767            break;            break;
1768    
1769            case PT_WORD:            case PT_WORD:
1770            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||            OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
1771                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||                 _pcre_ucp_gentype[prop->chartype] == ucp_N ||
1772                 c == CHAR_UNDERSCORE;                 c == CHAR_UNDERSCORE;
1773            break;            break;
1774    
1775            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
1776    
# Line 1941  for (;;) Line 1981  for (;;)
1981        break;        break;
1982    
1983        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1984        case OP_CHARNC:        case OP_CHARI:
1985        if (clen == 0) break;        if (clen == 0) break;
1986    
1987  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
# Line 2127  for (;;) Line 2167  for (;;)
2167        break;        break;
2168    
2169        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2170        /* Match a negated single character. This is only used for one-byte        /* Match a negated single character casefully. This is only used for
2171        characters, that is, we know that d < 256. The character we are        one-byte characters, that is, we know that d < 256. The character we are
2172        checking (c) can be multibyte. */        checking (c) can be multibyte. */
2173    
2174        case OP_NOT:        case OP_NOT:
2175        if (clen > 0)        if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); }
2176          {        break;
2177          unsigned int otherd = ((ims & PCRE_CASELESS) != 0)? fcc[d] : d;  
2178          if (c != d && c != otherd) { ADD_NEW(state_offset + dlen + 1, 0); }        /*-----------------------------------------------------------------*/
2179          }        /* Match a negated single character caselessly. This is only used for
2180          one-byte characters, that is, we know that d < 256. The character we are
2181          checking (c) can be multibyte. */
2182    
2183          case OP_NOTI:
2184          if (clen > 0 && c != d && c != fcc[d])
2185            { ADD_NEW(state_offset + dlen + 1, 0); }
2186        break;        break;
2187    
2188        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2189          case OP_PLUSI:
2190          case OP_MINPLUSI:
2191          case OP_POSPLUSI:
2192          case OP_NOTPLUSI:
2193          case OP_NOTMINPLUSI:
2194          case OP_NOTPOSPLUSI:
2195          caseless = TRUE;
2196          codevalue -= OP_STARI - OP_STAR;
2197    
2198          /* Fall through */
2199        case OP_PLUS:        case OP_PLUS:
2200        case OP_MINPLUS:        case OP_MINPLUS:
2201        case OP_POSPLUS:        case OP_POSPLUS:
# Line 2151  for (;;) Line 2207  for (;;)
2207        if (clen > 0)        if (clen > 0)
2208          {          {
2209          unsigned int otherd = NOTACHAR;          unsigned int otherd = NOTACHAR;
2210          if ((ims & PCRE_CASELESS) != 0)          if (caseless)
2211            {            {
2212  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
2213            if (utf8 && d >= 128)            if (utf8 && d >= 128)
# Line 2179  for (;;) Line 2235  for (;;)
2235        break;        break;
2236    
2237        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2238          case OP_QUERYI:
2239          case OP_MINQUERYI:
2240          case OP_POSQUERYI:
2241          case OP_NOTQUERYI:
2242          case OP_NOTMINQUERYI:
2243          case OP_NOTPOSQUERYI:
2244          caseless = TRUE;
2245          codevalue -= OP_STARI - OP_STAR;
2246          /* Fall through */
2247        case OP_QUERY:        case OP_QUERY:
2248        case OP_MINQUERY:        case OP_MINQUERY:
2249        case OP_POSQUERY:        case OP_POSQUERY:
# Line 2189  for (;;) Line 2254  for (;;)
2254        if (clen > 0)        if (clen > 0)
2255          {          {
2256          unsigned int otherd = NOTACHAR;          unsigned int otherd = NOTACHAR;
2257          if ((ims & PCRE_CASELESS) != 0)          if (caseless)
2258            {            {
2259  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
2260            if (utf8 && d >= 128)            if (utf8 && d >= 128)
# Line 2215  for (;;) Line 2280  for (;;)
2280        break;        break;
2281    
2282        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2283          case OP_STARI:
2284          case OP_MINSTARI:
2285          case OP_POSSTARI:
2286          case OP_NOTSTARI:
2287          case OP_NOTMINSTARI:
2288          case OP_NOTPOSSTARI:
2289          caseless = TRUE;
2290          codevalue -= OP_STARI - OP_STAR;
2291          /* Fall through */
2292        case OP_STAR:        case OP_STAR:
2293        case OP_MINSTAR:        case OP_MINSTAR:
2294        case OP_POSSTAR:        case OP_POSSTAR:
# Line 2225  for (;;) Line 2299  for (;;)
2299        if (clen > 0)        if (clen > 0)
2300          {          {
2301          unsigned int otherd = NOTACHAR;          unsigned int otherd = NOTACHAR;
2302          if ((ims & PCRE_CASELESS) != 0)          if (caseless)
2303            {            {
2304  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
2305            if (utf8 && d >= 128)            if (utf8 && d >= 128)
# Line 2251  for (;;) Line 2325  for (;;)
2325        break;        break;
2326    
2327        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2328          case OP_EXACTI:
2329          case OP_NOTEXACTI:
2330          caseless = TRUE;
2331          codevalue -= OP_STARI - OP_STAR;
2332          /* Fall through */
2333        case OP_EXACT:        case OP_EXACT:
2334        case OP_NOTEXACT:        case OP_NOTEXACT:
2335        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
2336        if (clen > 0)        if (clen > 0)
2337          {          {
2338          unsigned int otherd = NOTACHAR;          unsigned int otherd = NOTACHAR;
2339          if ((ims & PCRE_CASELESS) != 0)          if (caseless)
2340            {            {
2341  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
2342            if (utf8 && d >= 128)            if (utf8 && d >= 128)
# Line 2281  for (;;) Line 2360  for (;;)
2360        break;        break;
2361    
2362        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2363          case OP_UPTOI:
2364          case OP_MINUPTOI:
2365          case OP_POSUPTOI:
2366          case OP_NOTUPTOI:
2367          case OP_NOTMINUPTOI:
2368          case OP_NOTPOSUPTOI:
2369          caseless = TRUE;
2370          codevalue -= OP_STARI - OP_STAR;
2371          /* Fall through */
2372        case OP_UPTO:        case OP_UPTO:
2373        case OP_MINUPTO:        case OP_MINUPTO:
2374        case OP_POSUPTO:        case OP_POSUPTO:
# Line 2292  for (;;) Line 2380  for (;;)
2380        if (clen > 0)        if (clen > 0)
2381          {          {
2382          unsigned int otherd = NOTACHAR;          unsigned int otherd = NOTACHAR;
2383          if ((ims & PCRE_CASELESS) != 0)          if (caseless)
2384            {            {
2385  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
2386            if (utf8 && d >= 128)            if (utf8 && d >= 128)
# Line 2435  for (;;) Line 2523  for (;;)
2523            sizeof(local_offsets)/sizeof(int),    /* size of same */            sizeof(local_offsets)/sizeof(int),    /* size of same */
2524            local_workspace,                      /* workspace vector */            local_workspace,                      /* workspace vector */
2525            sizeof(local_workspace)/sizeof(int),  /* size of same */            sizeof(local_workspace)/sizeof(int),  /* size of same */
2526            ims,                                  /* the current ims flags */            rlevel);                              /* function recursion level */
           rlevel,                               /* function recursion level */  
           recursing);                           /* pass on regex recursion */  
2527    
2528          if (rc == PCRE_ERROR_DFA_UITEM) return rc;          if (rc == PCRE_ERROR_DFA_UITEM) return rc;
2529          if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))          if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))
# Line 2476  for (;;) Line 2562  for (;;)
2562              cb.capture_top      = 1;              cb.capture_top      = 1;
2563              cb.capture_last     = -1;              cb.capture_last     = -1;
2564              cb.callout_data     = md->callout_data;              cb.callout_data     = md->callout_data;
2565                cb.mark             = NULL;   /* No (*MARK) support */
2566              if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */              if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */
2567              }              }
2568            if (rrc > 0) break;                      /* Fail this thread */            if (rrc > 0) break;                      /* Fail this thread */
# Line 2502  for (;;) Line 2589  for (;;)
2589            {            {
2590            int value = GET2(code, LINK_SIZE+2);            int value = GET2(code, LINK_SIZE+2);
2591            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
2592            if (recursing > 0)            if (md->recursive != NULL)
2593              { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); }              { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); }
2594            else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }            else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
2595            }            }
# Line 2526  for (;;) Line 2613  for (;;)
2613              sizeof(local_offsets)/sizeof(int),    /* size of same */              sizeof(local_offsets)/sizeof(int),    /* size of same */
2614              local_workspace,                      /* workspace vector */              local_workspace,                      /* workspace vector */
2615              sizeof(local_workspace)/sizeof(int),  /* size of same */              sizeof(local_workspace)/sizeof(int),  /* size of same */
2616              ims,                                  /* the current ims flags */              rlevel);                              /* function recursion level */
             rlevel,                               /* function recursion level */  
             recursing);                           /* pass on regex recursion */  
2617    
2618            if (rc == PCRE_ERROR_DFA_UITEM) return rc;            if (rc == PCRE_ERROR_DFA_UITEM) return rc;
2619            if ((rc >= 0) ==            if ((rc >= 0) ==
# Line 2543  for (;;) Line 2628  for (;;)
2628        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2629        case OP_RECURSE:        case OP_RECURSE:
2630          {          {
2631            dfa_recursion_info *ri;
2632          int local_offsets[1000];          int local_offsets[1000];
2633          int local_workspace[1000];          int local_workspace[1000];
2634            const uschar *callpat = start_code + GET(code, 1);
2635            int recno = (callpat == md->start_code)? 0 :
2636              GET2(callpat, 1 + LINK_SIZE);
2637          int rc;          int rc;
2638    
2639          DPRINTF(("%.*sStarting regex recursion %d\n", rlevel*2-2, SP,          DPRINTF(("%.*sStarting regex recursion\n", rlevel*2-2, SP));
2640            recursing + 1));  
2641            /* Check for repeating a recursion without advancing the subject
2642            pointer. This should catch convoluted mutual recursions. (Some simple
2643            cases are caught at compile time.) */
2644    
2645            for (ri = md->recursive; ri != NULL; ri = ri->prevrec)
2646              if (recno == ri->group_num && ptr == ri->subject_position)
2647                return PCRE_ERROR_RECURSELOOP;
2648    
2649            /* Remember this recursion and where we started it so as to
2650            catch infinite loops. */
2651    
2652            new_recursive.group_num = recno;
2653            new_recursive.subject_position = ptr;
2654            new_recursive.prevrec = md->recursive;
2655            md->recursive = &new_recursive;
2656    
2657          rc = internal_dfa_exec(          rc = internal_dfa_exec(
2658            md,                                   /* fixed match data */            md,                                   /* fixed match data */
2659            start_code + GET(code, 1),            /* this subexpression's code */            callpat,                              /* this subexpression's code */
2660            ptr,                                  /* where we currently are */            ptr,                                  /* where we currently are */
2661            (int)(ptr - start_subject),           /* start offset */            (int)(ptr - start_subject),           /* start offset */
2662            local_offsets,                        /* offset vector */            local_offsets,                        /* offset vector */
2663            sizeof(local_offsets)/sizeof(int),    /* size of same */            sizeof(local_offsets)/sizeof(int),    /* size of same */
2664            local_workspace,                      /* workspace vector */            local_workspace,                      /* workspace vector */
2665            sizeof(local_workspace)/sizeof(int),  /* size of same */            sizeof(local_workspace)/sizeof(int),  /* size of same */
2666            ims,                                  /* the current ims flags */            rlevel);                              /* function recursion level */
2667            rlevel,                               /* function recursion level */  
2668            recursing + 1);                       /* regex recurse level */          md->recursive = new_recursive.prevrec;  /* Done this recursion */
2669    
2670          DPRINTF(("%.*sReturn from regex recursion %d: rc=%d\n", rlevel*2-2, SP,          DPRINTF(("%.*sReturn from regex recursion: rc=%d\n", rlevel*2-2, SP,
2671            recursing + 1, rc));            rc));
2672    
2673          /* Ran out of internal offsets */          /* Ran out of internal offsets */
2674    
# Line 2597  for (;;) Line 2701  for (;;)
2701        break;        break;
2702    
2703        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2704          case OP_BRAPOS:
2705          case OP_SBRAPOS:
2706          case OP_CBRAPOS:
2707          case OP_SCBRAPOS:
2708          case OP_BRAPOSZERO:
2709            {
2710            int charcount, matched_count;
2711            const uschar *local_ptr = ptr;
2712            BOOL allow_zero;
2713    
2714            if (codevalue == OP_BRAPOSZERO)
2715              {
2716              allow_zero = TRUE;
2717              codevalue = *(++code);  /* Codevalue will be one of above BRAs */
2718              }
2719            else allow_zero = FALSE;
2720    
2721            /* Loop to match the subpattern as many times as possible as if it were
2722            a complete pattern. */
2723    
2724            for (matched_count = 0;; matched_count++)
2725              {
2726              int local_offsets[2];
2727              int local_workspace[1000];
2728    
2729              int rc = internal_dfa_exec(
2730                md,                                   /* fixed match data */
2731                code,                                 /* this subexpression's code */
2732                local_ptr,                            /* where we currently are */
2733                (int)(ptr - start_subject),           /* start offset */
2734                local_offsets,                        /* offset vector */
2735                sizeof(local_offsets)/sizeof(int),    /* size of same */
2736                local_workspace,                      /* workspace vector */
2737                sizeof(local_workspace)/sizeof(int),  /* size of same */
2738                rlevel);                              /* function recursion level */
2739    
2740              /* Failed to match */
2741    
2742              if (rc < 0)
2743                {
2744                if (rc != PCRE_ERROR_NOMATCH) return rc;
2745                break;
2746                }
2747    
2748              /* Matched: break the loop if zero characters matched. */
2749    
2750              charcount = local_offsets[1] - local_offsets[0];
2751              if (charcount == 0) break;
2752              local_ptr += charcount;    /* Advance temporary position ptr */
2753              }
2754    
2755            /* At this point we have matched the subpattern matched_count
2756            times, and local_ptr is pointing to the character after the end of the
2757            last match. */
2758    
2759            if (matched_count > 0 || allow_zero)
2760              {
2761              const uschar *end_subpattern = code;
2762              int next_state_offset;
2763    
2764              do { end_subpattern += GET(end_subpattern, 1); }
2765                while (*end_subpattern == OP_ALT);
2766              next_state_offset =
2767                (int)(end_subpattern - start_code + LINK_SIZE + 1);
2768    
2769              /* Optimization: if there are no more active states, and there
2770              are no new states yet set up, then skip over the subject string
2771              right here, to save looping. Otherwise, set up the new state to swing
2772              into action when the end of the matched substring is reached. */
2773    
2774              if (i + 1 >= active_count && new_count == 0)
2775                {
2776                ptr = local_ptr;
2777                clen = 0;
2778                ADD_NEW(next_state_offset, 0);
2779                }
2780              else
2781                {
2782                const uschar *p = ptr;
2783                const uschar *pp = local_ptr;
2784                charcount = pp - p;
2785                while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;
2786                ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
2787                }
2788              }
2789            }
2790          break;
2791    
2792          /*-----------------------------------------------------------------*/
2793        case OP_ONCE:        case OP_ONCE:
2794          case OP_ONCE_NC:
2795          {          {
2796          int local_offsets[2];          int local_offsets[2];
2797          int local_workspace[1000];          int local_workspace[1000];
# Line 2611  for (;;) Line 2805  for (;;)
2805            sizeof(local_offsets)/sizeof(int),    /* size of same */            sizeof(local_offsets)/sizeof(int),    /* size of same */
2806            local_workspace,                      /* workspace vector */            local_workspace,                      /* workspace vector */
2807            sizeof(local_workspace)/sizeof(int),  /* size of same */            sizeof(local_workspace)/sizeof(int),  /* size of same */
2808            ims,                                  /* the current ims flags */            rlevel);                              /* function recursion level */
           rlevel,                               /* function recursion level */  
           recursing);                           /* pass on regex recursion */  
2809    
2810          if (rc >= 0)          if (rc >= 0)
2811            {            {
# Line 2623  for (;;) Line 2815  for (;;)
2815    
2816            do { end_subpattern += GET(end_subpattern, 1); }            do { end_subpattern += GET(end_subpattern, 1); }
2817              while (*end_subpattern == OP_ALT);              while (*end_subpattern == OP_ALT);
2818            next_state_offset =            next_state_offset =
2819              (int)(end_subpattern - start_code + LINK_SIZE + 1);              (int)(end_subpattern - start_code + LINK_SIZE + 1);
2820    
2821            /* If the end of this subpattern is KETRMAX or KETRMIN, we must            /* If the end of this subpattern is KETRMAX or KETRMIN, we must
# Line 2647  for (;;) Line 2839  for (;;)
2839            /* Optimization: if there are no more active states, and there            /* Optimization: if there are no more active states, and there
2840            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
2841            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
2842            into action when the end of the substring is reached. */            into action when the end of the matched substring is reached. */
2843    
2844            else if (i + 1 >= active_count && new_count == 0)            else if (i + 1 >= active_count && new_count == 0)
2845              {              {
# Line 2677  for (;;) Line 2869  for (;;)
2869              if (repeat_state_offset >= 0)              if (repeat_state_offset >= 0)
2870                { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }                { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }
2871              }              }
   
2872            }            }
2873          else if (rc != PCRE_ERROR_NOMATCH) return rc;          else if (rc != PCRE_ERROR_NOMATCH) return rc;
2874          }          }
# Line 2704  for (;;) Line 2895  for (;;)
2895          cb.capture_top      = 1;          cb.capture_top      = 1;
2896          cb.capture_last     = -1;          cb.capture_last     = -1;
2897          cb.callout_data     = md->callout_data;          cb.callout_data     = md->callout_data;
2898            cb.mark             = NULL;   /* No (*MARK) support */
2899          if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */          if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */
2900          }          }
2901        if (rrc == 0)        if (rrc == 0)
# Line 2744  for (;;) Line 2936  for (;;)
2936          ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */          ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */
2937           match_count < 0)                            /* no matches */           match_count < 0)                            /* no matches */
2938          ) &&                                         /* And... */          ) &&                                         /* And... */
2939          ptr >= end_subject &&                     /* Reached end of subject */          ptr >= end_subject &&                  /* Reached end of subject */
2940          ptr > current_subject)                    /* Matched non-empty string */          ptr > md->start_used_ptr)              /* Inspected non-empty string */
2941        {        {
2942        if (offsetcount >= 2)        if (offsetcount >= 2)
2943          {          {
# Line 2835  if (re == NULL || subject == NULL || wor Line 3027  if (re == NULL || subject == NULL || wor
3027     (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;     (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
3028  if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;  if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
3029  if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE;  if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE;
3030    if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;
3031    
3032  /* We need to find the pointer to any study data before we test for byte  /* We need to find the pointer to any study data before we test for byte
3033  flipping, so we scan the extra_data block first. This may set two fields in the  flipping, so we scan the extra_data block first. This may set two fields in the
# Line 2953  back the character offset. */ Line 3146  back the character offset. */
3146  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
3147  if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)  if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)
3148    {    {
3149    if (_pcre_valid_utf8((uschar *)subject, length) >= 0)    int erroroffset;
3150      return PCRE_ERROR_BADUTF8;    int errorcode = _pcre_valid_utf8((uschar *)subject, length, &erroroffset);
3151    if (start_offset > 0 && start_offset < length)    if (errorcode != 0)
3152      {      {
3153      int tb = ((uschar *)subject)[start_offset];      if (offsetcount >= 2)
     if (tb > 127)  
3154        {        {
3155        tb &= 0xc0;        offsets[0] = erroroffset;
3156        if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET;        offsets[1] = errorcode;
3157        }        }
3158        return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0)?
3159          PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
3160      }      }
3161      if (start_offset > 0 && start_offset < length &&
3162            (((USPTR)subject)[start_offset] & 0xc0) == 0x80)
3163        return PCRE_ERROR_BADUTF8_OFFSET;
3164    }    }
3165  #endif  #endif
3166    
# Line 3049  for (;;) Line 3246  for (;;)
3246    
3247      /* There are some optimizations that avoid running the match if a known      /* There are some optimizations that avoid running the match if a known
3248      starting point is not found. However, there is an option that disables      starting point is not found. However, there is an option that disables
3249      these, for testing and for ensuring that all callouts do actually occur. */      these, for testing and for ensuring that all callouts do actually occur.
3250        The option can be set in the regex by (*NO_START_OPT) or passed in
3251        match-time options. */
3252    
3253      if ((options & PCRE_NO_START_OPTIMIZE) == 0)      if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
3254        {        {
3255        /* Advance to a known first byte. */        /* Advance to a known first byte. */
3256    
# Line 3109  for (;;) Line 3308  for (;;)
3308          while (current_subject < end_subject)          while (current_subject < end_subject)
3309            {            {
3310            register unsigned int c = *current_subject;            register unsigned int c = *current_subject;
3311            if ((start_bits[c/8] & (1 << (c&7))) == 0) current_subject++;            if ((start_bits[c/8] & (1 << (c&7))) == 0)
3312              else break;              {
3313                current_subject++;
3314    #ifdef SUPPORT_UTF8
3315                if (utf8)
3316                  while(current_subject < end_subject &&
3317                        (*current_subject & 0xc0) == 0x80) current_subject++;
3318    #endif
3319                }
3320              else break;
3321            }            }
3322          }          }
3323        }        }
# Line 3123  for (;;) Line 3330  for (;;)
3330      disabling is explicitly requested (and of course, by the test above, this      disabling is explicitly requested (and of course, by the test above, this
3331      code is not obeyed when restarting after a partial match). */      code is not obeyed when restarting after a partial match). */
3332    
3333      if ((options & PCRE_NO_START_OPTIMIZE) == 0 &&      if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 &&
3334          (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0)          (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0)
3335        {        {
3336        /* 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 3191  for (;;) Line 3398  for (;;)
3398    /* OK, now we can do the business */    /* OK, now we can do the business */
3399    
3400    md->start_used_ptr = current_subject;    md->start_used_ptr = current_subject;
3401      md->recursive = NULL;
3402    
3403    rc = internal_dfa_exec(    rc = internal_dfa_exec(
3404      md,                                /* fixed match data */      md,                                /* fixed match data */
# Line 3201  for (;;) Line 3409  for (;;)
3409      offsetcount,                       /* size of same */      offsetcount,                       /* size of same */
3410      workspace,                         /* workspace vector */      workspace,                         /* workspace vector */
3411      wscount,                           /* size of same */      wscount,                           /* size of same */
3412      re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL), /* ims flags */      0);                                /* function recurse level */
     0,                                 /* function recurse level */  
     0);                                /* regex recurse level */  
3413    
3414    /* Anything other than "no match" means we are done, always; otherwise, carry    /* Anything other than "no match" means we are done, always; otherwise, carry
3415    on only if not anchored. */    on only if not anchored. */

Legend:
Removed from v.530  
changed lines
  Added in v.728

  ViewVC Help
Powered by ViewVC 1.1.5