/[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 361 by ph10, Thu Jul 10 16:03:28 2008 UTC revision 439 by ph10, Tue Sep 8 17:27:24 2009 UTC
# Line 3  Line 3 
3  *************************************************/  *************************************************/
4    
5  /* PCRE is a library of functions to support regular expressions whose syntax  /* PCRE is a library of functions to support regular expressions whose syntax
6  and semantics are as close as possible to those of the Perl 5 language.  and semantics are as close as possible to those of the Perl 5 language (but see
7    below for why this module is different).
8    
9                         Written by Philip Hazel                         Written by Philip Hazel
10             Copyright (c) 1997-2008 University of Cambridge             Copyright (c) 1997-2009 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 44  FSM). This is NOT Perl- compatible, but Line 45  FSM). This is NOT Perl- compatible, but
45  applications. */  applications. */
46    
47    
48    /* NOTE ABOUT PERFORMANCE: A user of this function sent some code that improved
49    the performance of his patterns greatly. I could not use it as it stood, as it
50    was not thread safe, and made assumptions about pattern sizes. Also, it caused
51    test 7 to loop, and test 9 to crash with a segfault.
52    
53    The issue is the check for duplicate states, which is done by a simple linear
54    search up the state list. (Grep for "duplicate" below to find the code.) For
55    many patterns, there will never be many states active at one time, so a simple
56    linear search is fine. In patterns that have many active states, it might be a
57    bottleneck. The suggested code used an indexing scheme to remember which states
58    had previously been used for each character, and avoided the linear search when
59    it knew there was no chance of a duplicate. This was implemented when adding
60    states to the state lists.
61    
62    I wrote some thread-safe, not-limited code to try something similar at the time
63    of checking for duplicates (instead of when adding states), using index vectors
64    on the stack. It did give a 13% improvement with one specially constructed
65    pattern for certain subject strings, but on other strings and on many of the
66    simpler patterns in the test suite it did worse. The major problem, I think,
67    was the extra time to initialize the index. This had to be done for each call
68    of internal_dfa_exec(). (The supplied patch used a static vector, initialized
69    only once - I suspect this was the cause of the problems with the tests.)
70    
71    Overall, I concluded that the gains in some cases did not outweigh the losses
72    in others, so I abandoned this code. */
73    
74    
75    
76  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
77  #include "config.h"  #include "config.h"
78  #endif  #endif
# Line 60  applications. */ Line 89  applications. */
89  #define SP "                   "  #define SP "                   "
90    
91    
   
92  /*************************************************  /*************************************************
93  *      Code parameters and static tables         *  *      Code parameters and static tables         *
94  *************************************************/  *************************************************/
# Line 389  if (*first_op == OP_REVERSE) Line 417  if (*first_op == OP_REVERSE)
417        current_subject - start_subject : max_back;        current_subject - start_subject : max_back;
418      current_subject -= gone_back;      current_subject -= gone_back;
419      }      }
420    
421      /* Save the earliest consulted character */
422    
423      if (current_subject < md->start_used_ptr)
424        md->start_used_ptr = current_subject;
425    
426    /* Now we can process the individual branches. */    /* Now we can process the individual branches. */
427    
# Line 454  for (;;) Line 487  for (;;)
487    int i, j;    int i, j;
488    int clen, dlen;    int clen, dlen;
489    unsigned int c, d;    unsigned int c, d;
490      int forced_fail = 0;
491      int reached_end = 0;
492    
493    /* 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
494    new state list. */    new state list. */
# Line 511  for (;;) Line 546  for (;;)
546      stateblock *current_state = active_states + i;      stateblock *current_state = active_states + i;
547      const uschar *code;      const uschar *code;
548      int state_offset = current_state->offset;      int state_offset = current_state->offset;
549      int count, codevalue;      int count, codevalue, rrc;
550    
551  #ifdef DEBUG  #ifdef DEBUG
552      printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset);      printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset);
# Line 543  for (;;) Line 578  for (;;)
578          }          }
579        }        }
580    
581      /* Check for a duplicate state with the same count, and skip if found. */      /* Check for a duplicate state with the same count, and skip if found.
582        See the note at the head of this module about the possibility of improving
583        performance here. */
584    
585      for (j = 0; j < i; j++)      for (j = 0; j < i; j++)
586        {        {
# Line 624  for (;;) Line 661  for (;;)
661            ADD_ACTIVE(state_offset - GET(code, 1), 0);            ADD_ACTIVE(state_offset - GET(code, 1), 0);
662            }            }
663          }          }
664        else if (ptr > current_subject || (md->moptions & PCRE_NOTEMPTY) == 0)        else
665          {          {
666          if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;          reached_end++;    /* Count branches that reach the end */
667            else if (match_count > 0 && ++match_count * 2 >= offsetcount)          if (ptr > current_subject || (md->moptions & PCRE_NOTEMPTY) == 0)
668              match_count = 0;            {
669          count = ((match_count == 0)? offsetcount : match_count * 2) - 2;            if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;
670          if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));              else if (match_count > 0 && ++match_count * 2 >= offsetcount)
671          if (offsetcount >= 2)                match_count = 0;
672            {            count = ((match_count == 0)? offsetcount : match_count * 2) - 2;
673            offsets[0] = current_subject - start_subject;            if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));
674            offsets[1] = ptr - start_subject;            if (offsetcount >= 2)
675            DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,              {
676              offsets[1] - offsets[0], current_subject));              offsets[0] = current_subject - start_subject;
677            }              offsets[1] = ptr - start_subject;
678          if ((md->moptions & PCRE_DFA_SHORTEST) != 0)              DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,
679            {                offsets[1] - offsets[0], current_subject));
680            DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"              }
681              "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel,            if ((md->moptions & PCRE_DFA_SHORTEST) != 0)
682              match_count, rlevel*2-2, SP));              {
683            return match_count;              DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"
684            }                "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel,
685                  match_count, rlevel*2-2, SP));
686                return match_count;
687                }
688              }
689          }          }
690        break;        break;
691    
# Line 757  for (;;) Line 798  for (;;)
798        if ((md->moptions & PCRE_NOTEOL) == 0)        if ((md->moptions & PCRE_NOTEOL) == 0)
799          {          {
800          if (clen == 0 ||          if (clen == 0 ||
801              (IS_NEWLINE(ptr) &&              ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&
802                 ((ims & PCRE_MULTILINE) != 0 || ptr == end_subject - md->nllen)                 ((ims & PCRE_MULTILINE) != 0 || ptr == end_subject - md->nllen)
803              ))              ))
804            { ADD_ACTIVE(state_offset + 1, 0); }            { ADD_ACTIVE(state_offset + 1, 0); }
# Line 794  for (;;) Line 835  for (;;)
835          if (ptr > start_subject)          if (ptr > start_subject)
836            {            {
837            const uschar *temp = ptr - 1;            const uschar *temp = ptr - 1;
838              if (temp < md->start_used_ptr) md->start_used_ptr = temp;
839  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
840            if (utf8) BACKCHAR(temp);            if (utf8) BACKCHAR(temp);
841  #endif  #endif
# Line 802  for (;;) Line 844  for (;;)
844            }            }
845          else left_word = 0;          else left_word = 0;
846    
847          if (clen > 0) right_word = c < 256 && (ctypes[c] & ctype_word) != 0;          if (clen > 0)
848            else right_word = 0;            right_word = c < 256 && (ctypes[c] & ctype_word) != 0;
849            else              /* This is a fudge to ensure that if this is the */
850              {               /* last item in the pattern, we don't count it as */
851              reached_end--;  /* reached, thus disabling a partial match. */
852              right_word = 0;
853              }
854    
855          if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))          if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))
856            { ADD_ACTIVE(state_offset + 1, 0); }            { ADD_ACTIVE(state_offset + 1, 0); }
# Line 2157  for (;;) Line 2204  for (;;)
2204    
2205  /* ========================================================================== */  /* ========================================================================== */
2206        /* These are the opcodes for fancy brackets of various kinds. We have        /* These are the opcodes for fancy brackets of various kinds. We have
2207        to use recursion in order to handle them. The "always failing" assersion        to use recursion in order to handle them. The "always failing" assertion
2208        (?!) is optimised when compiling to OP_FAIL, so we have to support that,        (?!) is optimised to OP_FAIL when compiling, so we have to support that,
2209        though the other "backtracking verbs" are not supported. */        though the other "backtracking verbs" are not supported. */
2210    
2211        case OP_FAIL:        case OP_FAIL:
2212          forced_fail++;    /* Count FAILs for multiple states */
2213        break;        break;
2214    
2215        case OP_ASSERT:        case OP_ASSERT:
# Line 2200  for (;;) Line 2248  for (;;)
2248          {          {
2249          int local_offsets[1000];          int local_offsets[1000];
2250          int local_workspace[1000];          int local_workspace[1000];
2251          int condcode = code[LINK_SIZE+1];          int codelink = GET(code, 1);
2252            int condcode;
2253    
2254            /* Because of the way auto-callout works during compile, a callout item
2255            is inserted between OP_COND and an assertion condition. This does not
2256            happen for the other conditions. */
2257    
2258            if (code[LINK_SIZE+1] == OP_CALLOUT)
2259              {
2260              rrc = 0;
2261              if (pcre_callout != NULL)
2262                {
2263                pcre_callout_block cb;
2264                cb.version          = 1;   /* Version 1 of the callout block */
2265                cb.callout_number   = code[LINK_SIZE+2];
2266                cb.offset_vector    = offsets;
2267                cb.subject          = (PCRE_SPTR)start_subject;
2268                cb.subject_length   = end_subject - start_subject;
2269                cb.start_match      = current_subject - start_subject;
2270                cb.current_position = ptr - start_subject;
2271                cb.pattern_position = GET(code, LINK_SIZE + 3);
2272                cb.next_item_length = GET(code, 3 + 2*LINK_SIZE);
2273                cb.capture_top      = 1;
2274                cb.capture_last     = -1;
2275                cb.callout_data     = md->callout_data;
2276                if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */
2277                }
2278              if (rrc > 0) break;                      /* Fail this thread */
2279              code += _pcre_OP_lengths[OP_CALLOUT];    /* Skip callout data */
2280              }
2281    
2282            condcode = code[LINK_SIZE+1];
2283    
2284          /* Back reference conditions are not supported */          /* Back reference conditions are not supported */
2285    
# Line 2209  for (;;) Line 2288  for (;;)
2288          /* The DEFINE condition is always false */          /* The DEFINE condition is always false */
2289    
2290          if (condcode == OP_DEF)          if (condcode == OP_DEF)
2291            {            { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
           ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0);  
           }  
2292    
2293          /* The only supported version of OP_RREF is for the value RREF_ANY,          /* The only supported version of OP_RREF is for the value RREF_ANY,
2294          which means "test if in any recursion". We can't test for specifically          which means "test if in any recursion". We can't test for specifically
# Line 2221  for (;;) Line 2298  for (;;)
2298            {            {
2299            int value = GET2(code, LINK_SIZE+2);            int value = GET2(code, LINK_SIZE+2);
2300            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;            if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
2301            if (recursing > 0) { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); }            if (recursing > 0)
2302              else { ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0); }              { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); }
2303              else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
2304            }            }
2305    
2306          /* Otherwise, the condition is an assertion */          /* Otherwise, the condition is an assertion */
# Line 2252  for (;;) Line 2330  for (;;)
2330                  (condcode == OP_ASSERT || condcode == OP_ASSERTBACK))                  (condcode == OP_ASSERT || condcode == OP_ASSERTBACK))
2331              { ADD_ACTIVE(endasscode + LINK_SIZE + 1 - start_code, 0); }              { ADD_ACTIVE(endasscode + LINK_SIZE + 1 - start_code, 0); }
2332            else            else
2333              { ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0); }              { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
2334            }            }
2335          }          }
2336        break;        break;
# Line 2404  for (;;) Line 2482  for (;;)
2482        /* Handle callouts */        /* Handle callouts */
2483    
2484        case OP_CALLOUT:        case OP_CALLOUT:
2485          rrc = 0;
2486        if (pcre_callout != NULL)        if (pcre_callout != NULL)
2487          {          {
         int rrc;  
2488          pcre_callout_block cb;          pcre_callout_block cb;
2489          cb.version          = 1;   /* Version 1 of the callout block */          cb.version          = 1;   /* Version 1 of the callout block */
2490          cb.callout_number   = code[1];          cb.callout_number   = code[1];
# Line 2421  for (;;) Line 2499  for (;;)
2499          cb.capture_last     = -1;          cb.capture_last     = -1;
2500          cb.callout_data     = md->callout_data;          cb.callout_data     = md->callout_data;
2501          if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */          if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */
         if (rrc == 0) { ADD_ACTIVE(state_offset + 2 + 2*LINK_SIZE, 0); }  
2502          }          }
2503          if (rrc == 0)
2504            { ADD_ACTIVE(state_offset + _pcre_OP_lengths[OP_CALLOUT], 0); }
2505        break;        break;
2506    
2507    
# Line 2438  for (;;) Line 2517  for (;;)
2517    /* We have finished the processing at the current subject character. If no    /* We have finished the processing at the current subject character. If no
2518    new states have been set for the next character, we have found all the    new states have been set for the next character, we have found all the
2519    matches that we are going to find. If we are at the top level and partial    matches that we are going to find. If we are at the top level and partial
2520    matching has been requested, check for appropriate conditions. */    matching has been requested, check for appropriate conditions. The "forced_
2521      fail" variable counts the number of (*F) encountered for the character. If it
2522      is equal to the original active_count (saved in workspace[1]) it means that
2523      (*F) was found on every active state. In this case we don't want to give a
2524      partial match. */
2525    
2526    if (new_count <= 0)    if (new_count <= 0)
2527      {      {
2528      if (match_count < 0 &&                     /* No matches found */      if (rlevel == 1 &&                               /* Top level, and */
2529          rlevel == 1 &&                         /* Top level match function */          reached_end != workspace[1] &&               /* Not all reached end */
2530          (md->moptions & PCRE_PARTIAL) != 0 &&  /* Want partial matching */          forced_fail != workspace[1] &&               /* Not all forced fail & */
2531          ptr >= end_subject &&                  /* Reached end of subject */          (                                            /* either... */
2532          ptr > current_subject)                 /* Matched non-empty string */          (md->moptions & PCRE_PARTIAL_HARD) != 0      /* Hard partial */
2533            ||                                           /* or... */
2534            ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */
2535             match_count < 0)                            /* no matches */
2536            ) &&                                         /* And... */
2537            ptr >= end_subject &&                     /* Reached end of subject */
2538            ptr > current_subject)                    /* Matched non-empty string */
2539        {        {
2540        if (offsetcount >= 2)        if (offsetcount >= 2)
2541          {          {
2542          offsets[0] = current_subject - start_subject;          offsets[0] = md->start_used_ptr - start_subject;
2543          offsets[1] = end_subject - start_subject;          offsets[1] = end_subject - start_subject;
2544          }          }
2545        match_count = PCRE_ERROR_PARTIAL;        match_count = PCRE_ERROR_PARTIAL;
# Line 2614  switch ((((options & PCRE_NEWLINE_BITS) Line 2703  switch ((((options & PCRE_NEWLINE_BITS)
2703           PCRE_NEWLINE_BITS)           PCRE_NEWLINE_BITS)
2704    {    {
2705    case 0: newline = NEWLINE; break;   /* Compile-time default */    case 0: newline = NEWLINE; break;   /* Compile-time default */
2706    case PCRE_NEWLINE_CR: newline = '\r'; break;    case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
2707    case PCRE_NEWLINE_LF: newline = '\n'; break;    case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
2708    case PCRE_NEWLINE_CR+    case PCRE_NEWLINE_CR+
2709         PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; break;         PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
2710    case PCRE_NEWLINE_ANY: newline = -1; break;    case PCRE_NEWLINE_ANY: newline = -1; break;
2711    case PCRE_NEWLINE_ANYCRLF: newline = -2; break;    case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
2712    default: return PCRE_ERROR_BADNEWLINE;    default: return PCRE_ERROR_BADNEWLINE;
# Line 2713  if ((re->flags & PCRE_REQCHSET) != 0) Line 2802  if ((re->flags & PCRE_REQCHSET) != 0)
2802    }    }
2803    
2804  /* 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
2805  failed match. Unless restarting, optimize by moving to the first match  failed match. If not restarting, perform certain optimizations at the start of
2806  character if possible, when not anchored. Then unless wanting a partial match,  a match. */
 check for a required later character. */  
2807    
2808  for (;;)  for (;;)
2809    {    {
# Line 2725  for (;;) Line 2813  for (;;)
2813      {      {
2814      const uschar *save_end_subject = end_subject;      const uschar *save_end_subject = end_subject;
2815    
2816      /* Advance to a unique first char if possible. If firstline is TRUE, the      /* If firstline is TRUE, the start of the match is constrained to the first
2817      start of the match is constrained to the first line of a multiline string.      line of a multiline string. Implement this by temporarily adjusting
2818      Implement this by temporarily adjusting end_subject so that we stop      end_subject so that we stop scanning at a newline. If the match fails at
2819      scanning at a newline. If the match fails at the newline, later code breaks      the newline, later code breaks this loop. */
     this loop. */  
2820    
2821      if (firstline)      if (firstline)
2822        {        {
2823        const uschar *t = current_subject;        USPTR t = current_subject;
2824    #ifdef SUPPORT_UTF8
2825          if (utf8)
2826            {
2827            while (t < md->end_subject && !IS_NEWLINE(t))
2828              {
2829              t++;
2830              while (t < end_subject && (*t & 0xc0) == 0x80) t++;
2831              }
2832            }
2833          else
2834    #endif
2835        while (t < md->end_subject && !IS_NEWLINE(t)) t++;        while (t < md->end_subject && !IS_NEWLINE(t)) t++;
2836        end_subject = t;        end_subject = t;
2837        }        }
2838    
2839      if (first_byte >= 0)      /* There are some optimizations that avoid running the match if a known
2840        starting point is not found, or if a known later character is not present.
2841        However, there is an option that disables these, for testing and for
2842        ensuring that all callouts do actually occur. */
2843    
2844        if ((options & PCRE_NO_START_OPTIMIZE) == 0)
2845        {        {
       if (first_byte_caseless)  
         while (current_subject < end_subject &&  
                lcc[*current_subject] != first_byte)  
           current_subject++;  
       else  
         while (current_subject < end_subject && *current_subject != first_byte)  
           current_subject++;  
       }  
2846    
2847      /* Or to just after a linebreak for a multiline match if possible */        /* Advance to a known first byte. */
2848    
2849      else if (startline)        if (first_byte >= 0)
       {  
       if (current_subject > md->start_subject + start_offset)  
2850          {          {
2851          while (current_subject < end_subject && !WAS_NEWLINE(current_subject))          if (first_byte_caseless)
2852            current_subject++;            while (current_subject < end_subject &&
2853                     lcc[*current_subject] != first_byte)
2854                current_subject++;
2855            else
2856              while (current_subject < end_subject &&
2857                     *current_subject != first_byte)
2858                current_subject++;
2859            }
2860    
2861          /* Or to just after a linebreak for a multiline match if possible */
2862    
2863          else if (startline)
2864            {
2865            if (current_subject > md->start_subject + start_offset)
2866              {
2867    #ifdef SUPPORT_UTF8
2868              if (utf8)
2869                {
2870                while (current_subject < end_subject &&
2871                       !WAS_NEWLINE(current_subject))
2872                  {
2873                  current_subject++;
2874                  while(current_subject < end_subject &&
2875                        (*current_subject & 0xc0) == 0x80)
2876                    current_subject++;
2877                  }
2878                }
2879              else
2880    #endif
2881              while (current_subject < end_subject && !WAS_NEWLINE(current_subject))
2882                current_subject++;
2883    
2884              /* If we have just passed a CR and the newline option is ANY or
2885              ANYCRLF, and we are now at a LF, advance the match position by one
2886              more character. */
2887    
2888          /* If we have just passed a CR and the newline option is ANY or            if (current_subject[-1] == CHAR_CR &&
2889          ANYCRLF, and we are now at a LF, advance the match position by one more                 (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
2890          character. */                 current_subject < end_subject &&
2891                   *current_subject == CHAR_NL)
2892          if (current_subject[-1] == '\r' &&              current_subject++;
2893               (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&            }
              current_subject < end_subject &&  
              *current_subject == '\n')  
           current_subject++;  
2894          }          }
       }  
2895    
2896      /* Or to a non-unique first char after study */        /* Or to a non-unique first char after study */
2897    
2898      else if (start_bits != NULL)        else if (start_bits != NULL)
       {  
       while (current_subject < end_subject)  
2899          {          {
2900          register unsigned int c = *current_subject;          while (current_subject < end_subject)
2901          if ((start_bits[c/8] & (1 << (c&7))) == 0) current_subject++;            {
2902            else break;            register unsigned int c = *current_subject;
2903              if ((start_bits[c/8] & (1 << (c&7))) == 0) current_subject++;
2904                else break;
2905              }
2906          }          }
2907        }        }
2908    
# Line 2800  for (;;) Line 2924  for (;;)
2924    showed up when somebody was matching /^C/ on a 32-megabyte string... so we    showed up when somebody was matching /^C/ on a 32-megabyte string... so we
2925    don't do this when the string is sufficiently long.    don't do this when the string is sufficiently long.
2926    
2927    ALSO: this processing is disabled when partial matching is requested.    ALSO: this processing is disabled when partial matching is requested, and can
2928    */    also be explicitly deactivated. Furthermore, we have to disable when
2929      restarting after a partial match, because the required character may have
2930      already been matched. */
2931    
2932    if (req_byte >= 0 &&    if ((options & PCRE_NO_START_OPTIMIZE) == 0 &&
2933          req_byte >= 0 &&
2934        end_subject - current_subject < REQ_BYTE_MAX &&        end_subject - current_subject < REQ_BYTE_MAX &&
2935        (options & PCRE_PARTIAL) == 0)        (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_DFA_RESTART)) == 0)
2936      {      {
2937      register const uschar *p = current_subject + ((first_byte >= 0)? 1 : 0);      register const uschar *p = current_subject + ((first_byte >= 0)? 1 : 0);
2938    
# Line 2845  for (;;) Line 2972  for (;;)
2972    
2973    /* OK, now we can do the business */    /* OK, now we can do the business */
2974    
2975      md->start_used_ptr = current_subject;
2976    
2977    rc = internal_dfa_exec(    rc = internal_dfa_exec(
2978      md,                                /* fixed match data */      md,                                /* fixed match data */
2979      md->start_code,                    /* this subexpression's code */      md->start_code,                    /* this subexpression's code */
# Line 2879  for (;;) Line 3008  for (;;)
3008    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
3009    or ANY or ANYCRLF, advance the match position by one more character. */    or ANY or ANYCRLF, advance the match position by one more character. */
3010    
3011    if (current_subject[-1] == '\r' &&    if (current_subject[-1] == CHAR_CR &&
3012        current_subject < end_subject &&        current_subject < end_subject &&
3013        *current_subject == '\n' &&        *current_subject == CHAR_NL &&
3014        (re->flags & PCRE_HASCRORLF) == 0 &&        (re->flags & PCRE_HASCRORLF) == 0 &&
3015          (md->nltype == NLTYPE_ANY ||          (md->nltype == NLTYPE_ANY ||
3016           md->nltype == NLTYPE_ANYCRLF ||           md->nltype == NLTYPE_ANYCRLF ||

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

  ViewVC Help
Powered by ViewVC 1.1.5