/[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 91 by nigel, Sat Feb 24 21:41:34 2007 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-2006 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 39  POSSIBILITY OF SUCH DAMAGE. Line 40  POSSIBILITY OF SUCH DAMAGE.
40    
41    
42  /* This module contains the external function pcre_dfa_exec(), which is an  /* This module contains the external function pcre_dfa_exec(), which is an
43  alternative matching function that uses a DFA algorithm. This is NOT Perl-  alternative matching function that uses a sort of DFA algorithm (not a true
44  compatible, but it has advantages in certain applications. */  FSM). This is NOT Perl- compatible, but it has advantages in certain
45    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
77    #include "config.h"
78    #endif
79    
80    #define NLBLOCK md             /* Block containing newline information */
81    #define PSSTART start_subject  /* Field containing processed string start */
82    #define PSEND   end_subject    /* Field containing processed string end */
83    
 #define NLBLOCK md           /* The block containing newline information */  
84  #include "pcre_internal.h"  #include "pcre_internal.h"
85    
86    
# Line 52  compatible, but it has advantages in cer Line 89  compatible, but it has advantages in cer
89  #define SP "                   "  #define SP "                   "
90    
91    
   
92  /*************************************************  /*************************************************
93  *      Code parameters and static tables         *  *      Code parameters and static tables         *
94  *************************************************/  *************************************************/
95    
96  /* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes  /* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes
97  into others, under special conditions. A gap of 10 between the blocks should be  into others, under special conditions. A gap of 20 between the blocks should be
98  enough. */  enough. The resulting opcodes don't have to be less than 256 because they are
99    never stored, so we push them well clear of the normal opcodes. */
100  #define OP_PROP_EXTRA    (EXTRACT_BASIC_MAX+1)  
101  #define OP_EXTUNI_EXTRA  (EXTRACT_BASIC_MAX+11)  #define OP_PROP_EXTRA       300
102    #define OP_EXTUNI_EXTRA     320
103    #define OP_ANYNL_EXTRA      340
104    #define OP_HSPACE_EXTRA     360
105    #define OP_VSPACE_EXTRA     380
106    
107    
108  /* This table identifies those opcodes that are followed immediately by a  /* This table identifies those opcodes that are followed immediately by a
109  character that is to be tested in some way. This makes is possible to  character that is to be tested in some way. This makes is possible to
110  centralize the loading of these characters. In the case of Type * etc, the  centralize the loading of these characters. In the case of Type * etc, the
111  "character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a  "character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a
112  small value. */  small value. ***NOTE*** If the start of this table is modified, the two tables
113    that follow must also be modified. */
114    
115  static uschar coptable[] = {  static const uschar coptable[] = {
116    0,                             /* End                                    */    0,                             /* End                                    */
117    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* \A, \G, \B, \b, \D, \d, \S, \s, \W, \w */    0, 0, 0, 0, 0,                 /* \A, \G, \K, \B, \b                     */
118    0, 0,                          /* Any, Anybyte                           */    0, 0, 0, 0, 0, 0,              /* \D, \d, \S, \s, \W, \w                 */
119      0, 0, 0,                       /* Any, AllAny, Anybyte                   */
120    0, 0, 0,                       /* NOTPROP, PROP, EXTUNI                  */    0, 0, 0,                       /* NOTPROP, PROP, EXTUNI                  */
121      0, 0, 0, 0, 0,                 /* \R, \H, \h, \V, \v                     */
122    0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, $                      */    0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, $                      */
123    1,                             /* Char                                   */    1,                             /* Char                                   */
124    1,                             /* Charnc                                 */    1,                             /* Charnc                                 */
# Line 83  static uschar coptable[] = { Line 126  static uschar coptable[] = {
126    /* Positive single-char repeats                                          */    /* Positive single-char repeats                                          */
127    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */    1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
128    3, 3, 3,                       /* upto, minupto, exact                   */    3, 3, 3,                       /* upto, minupto, exact                   */
129      1, 1, 1, 3,                    /* *+, ++, ?+, upto+                      */
130    /* Negative single-char repeats - only for chars < 256                   */    /* Negative single-char repeats - only for chars < 256                   */
131    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */    1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
132    3, 3, 3,                       /* NOT upto, minupto, exact               */    3, 3, 3,                       /* NOT upto, minupto, exact               */
133      1, 1, 1, 3,                    /* NOT *+, ++, ?+, updo+                  */
134    /* Positive type repeats                                                 */    /* Positive type repeats                                                 */
135    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */    1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
136    3, 3, 3,                       /* Type upto, minupto, exact              */    3, 3, 3,                       /* Type upto, minupto, exact              */
137      1, 1, 1, 3,                    /* Type *+, ++, ?+, upto+                 */
138    /* Character class & ref repeats                                         */    /* Character class & ref repeats                                         */
139    0, 0, 0, 0, 0, 0,              /* *, *?, +, +?, ?, ??                    */    0, 0, 0, 0, 0, 0,              /* *, *?, +, +?, ?, ??                    */
140    0, 0,                          /* CRRANGE, CRMINRANGE                    */    0, 0,                          /* CRRANGE, CRMINRANGE                    */
# Line 107  static uschar coptable[] = { Line 153  static uschar coptable[] = {
153    0,                             /* Assert behind                          */    0,                             /* Assert behind                          */
154    0,                             /* Assert behind not                      */    0,                             /* Assert behind not                      */
155    0,                             /* Reverse                                */    0,                             /* Reverse                                */
156    0,                             /* Once                                   */    0, 0, 0, 0,                    /* ONCE, BRA, CBRA, COND                  */
157    0,                             /* COND                                   */    0, 0, 0,                       /* SBRA, SCBRA, SCOND                     */
158    0,                             /* CREF                                   */    0,                             /* CREF                                   */
159      0,                             /* RREF                                   */
160      0,                             /* DEF                                    */
161    0, 0,                          /* BRAZERO, BRAMINZERO                    */    0, 0,                          /* BRAZERO, BRAMINZERO                    */
162    0,                             /* BRANUMBER                              */    0, 0, 0, 0,                    /* PRUNE, SKIP, THEN, COMMIT              */
163    0                              /* BRA                                    */    0, 0, 0                        /* FAIL, ACCEPT, SKIPZERO                 */
164  };  };
165    
166  /* 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,
167  and \w */  and \w */
168    
169  static uschar toptable1[] = {  static const uschar toptable1[] = {
170    0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0,
171    ctype_digit, ctype_digit,    ctype_digit, ctype_digit,
172    ctype_space, ctype_space,    ctype_space, ctype_space,
173    ctype_word,  ctype_word,    ctype_word,  ctype_word,
174    0                               /* OP_ANY */    0, 0                            /* OP_ANY, OP_ALLANY */
175  };  };
176    
177  static uschar toptable2[] = {  static const uschar toptable2[] = {
178    0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0,
179    ctype_digit, 0,    ctype_digit, 0,
180    ctype_space, 0,    ctype_space, 0,
181    ctype_word,  0,    ctype_word,  0,
182    1                               /* OP_ANY */    1, 1                            /* OP_ANY, OP_ALLANY */
183  };  };
184    
185    
# Line 203  Arguments: Line 251  Arguments:
251    rlevel            function call recursion level    rlevel            function call recursion level
252    recursing         regex recursive call level    recursing         regex recursive call level
253    
254  Returns:            > 0 =>  Returns:            > 0 => number of match offset pairs placed in offsets
255                      = 0 =>                      = 0 => offsets overflowed; longest matches are present
256                       -1 => failed to match                       -1 => failed to match
257                     < -1 => some kind of unexpected problem                     < -1 => some kind of unexpected problem
258    
# Line 278  stateblock *next_active_state, *next_new Line 326  stateblock *next_active_state, *next_new
326    
327  const uschar *ctypes, *lcc, *fcc;  const uschar *ctypes, *lcc, *fcc;
328  const uschar *ptr;  const uschar *ptr;
329  const uschar *end_code;  const uschar *end_code, *first_op;
330    
331  int active_count, new_count, match_count;  int active_count, new_count, match_count;
332    
# Line 291  const uschar *start_code = md->start_cod Line 339  const uschar *start_code = md->start_cod
339    
340  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
341  BOOL utf8 = (md->poptions & PCRE_UTF8) != 0;  BOOL utf8 = (md->poptions & PCRE_UTF8) != 0;
342    #else
343    BOOL utf8 = FALSE;
344  #endif  #endif
345    
346  rlevel++;  rlevel++;
# Line 314  active_states = (stateblock *)(workspace Line 364  active_states = (stateblock *)(workspace
364  next_new_state = new_states = active_states + wscount;  next_new_state = new_states = active_states + wscount;
365  new_count = 0;  new_count = 0;
366    
367    first_op = this_start_code + 1 + LINK_SIZE +
368      ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA)? 2:0);
369    
370  /* 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
371  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
372  makes is possible to use this function recursively, when we want to stop at a  makes is possible to use this function recursively, when we want to stop at a
# Line 323  If the first opcode in the first alterna Line 376  If the first opcode in the first alterna
376  a backward assertion. In that case, we have to find out the maximum amount to  a backward assertion. In that case, we have to find out the maximum amount to
377  move back, and set up each alternative appropriately. */  move back, and set up each alternative appropriately. */
378    
379  if (this_start_code[1+LINK_SIZE] == OP_REVERSE)  if (*first_op == OP_REVERSE)
380    {    {
381    int max_back = 0;    int max_back = 0;
382    int gone_back;    int gone_back;
# Line 364  if (this_start_code[1+LINK_SIZE] == OP_R Line 417  if (this_start_code[1+LINK_SIZE] == OP_R
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 405  else Line 463  else
463    
464    else    else
465      {      {
466        int length = 1 + LINK_SIZE +
467          ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA)? 2:0);
468      do      do
469        {        {
470        ADD_NEW(end_code - start_code + 1 + LINK_SIZE, 0);        ADD_NEW(end_code - start_code + length, 0);
471        end_code += GET(end_code, 1);        end_code += GET(end_code, 1);
472          length = 1 + LINK_SIZE;
473        }        }
474      while (*end_code == OP_ALT);      while (*end_code == OP_ALT);
475      }      }
# Line 426  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 461  for (;;) Line 524  for (;;)
524    
525    if (ptr < end_subject)    if (ptr < end_subject)
526      {      {
527      clen = 1;      clen = 1;        /* Number of bytes in the character */
528  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
529      if (utf8) { GETCHARLEN(c, ptr, clen); } else      if (utf8) { GETCHARLEN(c, ptr, clen); } else
530  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF8 */
# Line 469  for (;;) Line 532  for (;;)
532      }      }
533    else    else
534      {      {
535      clen = 0;    /* At end subject */      clen = 0;        /* This indicates the end of the subject */
536      c = -1;      c = NOTACHAR;    /* This value should never actually be used */
537      }      }
538    
539    /* Scan up the active states and act on each one. The result of an action    /* Scan up the active states and act on each one. The result of an action
# Line 483  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;
     int chartype, script;  
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);
553      if (c < 0) printf("-1\n");      if (clen == 0) printf("EOL\n");
554        else if (c > 32 && c < 127) printf("'%c'\n", c);        else if (c > 32 && c < 127) printf("'%c'\n", c);
555          else printf("0x%02x\n", c);          else printf("0x%02x\n", c);
556  #endif  #endif
# Line 516  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 532  for (;;) Line 596  for (;;)
596    
597      code = start_code + state_offset;      code = start_code + state_offset;
598      codevalue = *code;      codevalue = *code;
     if (codevalue >= OP_BRA) codevalue = OP_BRA; /* All brackets are equal */  
599    
600      /* If this opcode is followed by an inline character, load it. It is      /* If this opcode is followed by an inline character, load it. It is
601      tempting to test for the presence of a subject character here, but that      tempting to test for the presence of a subject character here, but that
# Line 540  for (;;) Line 603  for (;;)
603      permitted.      permitted.
604    
605      We also use this mechanism for opcodes such as OP_TYPEPLUS that take an      We also use this mechanism for opcodes such as OP_TYPEPLUS that take an
606      argument that is not a data character - but is always one byte long.      argument that is not a data character - but is always one byte long. We
607      Unfortunately, we have to take special action to deal with  \P, \p, and      have to take special action to deal with  \P, \p, \H, \h, \V, \v and \X in
608      \X in this case. To keep the other cases fast, convert these ones to new      this case. To keep the other cases fast, convert these ones to new opcodes.
609      opcodes. */      */
610    
611      if (coptable[codevalue] > 0)      if (coptable[codevalue] > 0)
612        {        {
# Line 554  for (;;) Line 617  for (;;)
617        d = code[coptable[codevalue]];        d = code[coptable[codevalue]];
618        if (codevalue >= OP_TYPESTAR)        if (codevalue >= OP_TYPESTAR)
619          {          {
620          if (d == OP_ANYBYTE) return PCRE_ERROR_DFA_UITEM;          switch(d)
621          if (d >= OP_NOTPROP)            {
622            codevalue += (d == OP_EXTUNI)? OP_EXTUNI_EXTRA : OP_PROP_EXTRA;            case OP_ANYBYTE: return PCRE_ERROR_DFA_UITEM;
623              case OP_NOTPROP:
624              case OP_PROP: codevalue += OP_PROP_EXTRA; break;
625              case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break;
626              case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break;
627              case OP_NOT_HSPACE:
628              case OP_HSPACE: codevalue += OP_HSPACE_EXTRA; break;
629              case OP_NOT_VSPACE:
630              case OP_VSPACE: codevalue += OP_VSPACE_EXTRA; break;
631              default: break;
632              }
633          }          }
634        }        }
635      else      else
636        {        {
637        dlen = 0;         /* Not strictly necessary, but compilers moan */        dlen = 0;         /* Not strictly necessary, but compilers moan */
638        d = -1;           /* if these variables are not set. */        d = NOTACHAR;     /* if these variables are not set. */
639        }        }
640    
641    
# Line 588  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 624  for (;;) Line 701  for (;;)
701    
702        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
703        case OP_BRA:        case OP_BRA:
704          case OP_SBRA:
705        do        do
706          {          {
707          ADD_ACTIVE(code - start_code + 1 + LINK_SIZE, 0);          ADD_ACTIVE(code - start_code + 1 + LINK_SIZE, 0);
# Line 633  for (;;) Line 711  for (;;)
711        break;        break;
712    
713        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
714          case OP_CBRA:
715          case OP_SCBRA:
716          ADD_ACTIVE(code - start_code + 3 + LINK_SIZE,  0);
717          code += GET(code, 1);
718          while (*code == OP_ALT)
719            {
720            ADD_ACTIVE(code - start_code + 1 + LINK_SIZE,  0);
721            code += GET(code, 1);
722            }
723          break;
724    
725          /*-----------------------------------------------------------------*/
726        case OP_BRAZERO:        case OP_BRAZERO:
727        case OP_BRAMINZERO:        case OP_BRAMINZERO:
728        ADD_ACTIVE(state_offset + 1, 0);        ADD_ACTIVE(state_offset + 1, 0);
# Line 642  for (;;) Line 732  for (;;)
732        break;        break;
733    
734        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
735        case OP_BRANUMBER:        case OP_SKIPZERO:
736        ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0);        code += 1 + GET(code, 2);
737          while (*code == OP_ALT) code += GET(code, 1);
738          ADD_ACTIVE(code - start_code + 1 + LINK_SIZE, 0);
739        break;        break;
740    
741        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
742        case OP_CIRC:        case OP_CIRC:
743        if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||        if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||
744            ((ims & PCRE_MULTILINE) != 0 &&            ((ims & PCRE_MULTILINE) != 0 &&
             ptr >= start_subject + md->nllen &&  
745              ptr != end_subject &&              ptr != end_subject &&
746              IS_NEWLINE(ptr - md->nllen)))              WAS_NEWLINE(ptr)))
747          { ADD_ACTIVE(state_offset + 1, 0); }          { ADD_ACTIVE(state_offset + 1, 0); }
748        break;        break;
749    
# Line 686  for (;;) Line 777  for (;;)
777    
778        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
779        case OP_ANY:        case OP_ANY:
780        if (clen > 0 && ((ims & PCRE_DOTALL) != 0 ||        if (clen > 0 && !IS_NEWLINE(ptr))
781                         ptr > end_subject - md->nllen ||          { ADD_NEW(state_offset + 1, 0); }
782                         !IS_NEWLINE(ptr)))        break;
783    
784          /*-----------------------------------------------------------------*/
785          case OP_ALLANY:
786          if (clen > 0)
787          { ADD_NEW(state_offset + 1, 0); }          { ADD_NEW(state_offset + 1, 0); }
788        break;        break;
789    
790        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
791        case OP_EODN:        case OP_EODN:
792        if (clen == 0 ||        if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen))
            (ptr == end_subject - md->nllen && IS_NEWLINE(ptr)))  
793          { ADD_ACTIVE(state_offset + 1, 0); }          { ADD_ACTIVE(state_offset + 1, 0); }
794        break;        break;
795    
# Line 704  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              (ptr <= end_subject - md->nllen && 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); }
805          }          }
806        else if ((ims & PCRE_MULTILINE) != 0 &&        else if ((ims & PCRE_MULTILINE) != 0 && IS_NEWLINE(ptr))
                ptr <= end_subject - md->nllen && IS_NEWLINE(ptr))  
807          { ADD_ACTIVE(state_offset + 1, 0); }          { ADD_ACTIVE(state_offset + 1, 0); }
808        break;        break;
809    
# Line 742  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 750  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 759  for (;;) Line 858  for (;;)
858        break;        break;
859    
860    
 #ifdef SUPPORT_UCP  
   
861        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
862        /* Check the next character by Unicode property. We will get here only        /* Check the next character by Unicode property. We will get here only
863        if the support is in the binary; otherwise a compile-time error occurs.        if the support is in the binary; otherwise a compile-time error occurs.
864        */        */
865    
866    #ifdef SUPPORT_UCP
867        case OP_PROP:        case OP_PROP:
868        case OP_NOTPROP:        case OP_NOTPROP:
869        if (clen > 0)        if (clen > 0)
870          {          {
871          BOOL OK;          BOOL OK;
872          int category = _pcre_ucp_findprop(c, &chartype, &script);          const ucd_record * prop = GET_UCD(c);
873          switch(code[1])          switch(code[1])
874            {            {
875            case PT_ANY:            case PT_ANY:
# Line 779  for (;;) Line 877  for (;;)
877            break;            break;
878    
879            case PT_LAMP:            case PT_LAMP:
880            OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt;
881            break;            break;
882    
883            case PT_GC:            case PT_GC:
884            OK = category == code[2];            OK = _pcre_ucp_gentype[prop->chartype] == code[2];
885            break;            break;
886    
887            case PT_PC:            case PT_PC:
888            OK = chartype == code[2];            OK = prop->chartype == code[2];
889            break;            break;
890    
891            case PT_SC:            case PT_SC:
892            OK = script == code[2];            OK = prop->script == code[2];
893            break;            break;
894    
895            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
# Line 811  for (;;) Line 909  for (;;)
909  /* ========================================================================== */  /* ========================================================================== */
910        /* These opcodes likewise inspect the subject character, but have an        /* These opcodes likewise inspect the subject character, but have an
911        argument that is not a data character. It is one of these opcodes:        argument that is not a data character. It is one of these opcodes:
912        OP_ANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE, OP_WORDCHAR,        OP_ANY, OP_ALLANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE,
913        OP_NOT_WORDCHAR. The value is loaded into d. */        OP_WORDCHAR, OP_NOT_WORDCHAR. The value is loaded into d. */
914    
915        case OP_TYPEPLUS:        case OP_TYPEPLUS:
916        case OP_TYPEMINPLUS:        case OP_TYPEMINPLUS:
917          case OP_TYPEPOSPLUS:
918        count = current_state->count;  /* Already matched */        count = current_state->count;  /* Already matched */
919        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
920        if (clen > 0)        if (clen > 0)
921          {          {
922          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
923              (c < 256 &&              (c < 256 &&
924                (d != OP_ANY ||                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                (ims & PCRE_DOTALL) != 0 ||  
                ptr > end_subject - md->nllen ||  
                !IS_NEWLINE(ptr)  
               ) &&  
925                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
926            {            {
927              if (count > 0 && codevalue == OP_TYPEPOSPLUS)
928                {
929                active_count--;            /* Remove non-match possibility */
930                next_active_state--;
931                }
932            count++;            count++;
933            ADD_NEW(state_offset, count);            ADD_NEW(state_offset, count);
934            }            }
# Line 838  for (;;) Line 938  for (;;)
938        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
939        case OP_TYPEQUERY:        case OP_TYPEQUERY:
940        case OP_TYPEMINQUERY:        case OP_TYPEMINQUERY:
941          case OP_TYPEPOSQUERY:
942        ADD_ACTIVE(state_offset + 2, 0);        ADD_ACTIVE(state_offset + 2, 0);
943        if (clen > 0)        if (clen > 0)
944          {          {
945          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
946              (c < 256 &&              (c < 256 &&
947                (d != OP_ANY ||                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                (ims & PCRE_DOTALL) != 0 ||  
                ptr > end_subject - md->nllen ||  
                !IS_NEWLINE(ptr)  
               ) &&  
948                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
949            {            {
950              if (codevalue == OP_TYPEPOSQUERY)
951                {
952                active_count--;            /* Remove non-match possibility */
953                next_active_state--;
954                }
955            ADD_NEW(state_offset + 2, 0);            ADD_NEW(state_offset + 2, 0);
956            }            }
957          }          }
# Line 858  for (;;) Line 960  for (;;)
960        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
961        case OP_TYPESTAR:        case OP_TYPESTAR:
962        case OP_TYPEMINSTAR:        case OP_TYPEMINSTAR:
963          case OP_TYPEPOSSTAR:
964        ADD_ACTIVE(state_offset + 2, 0);        ADD_ACTIVE(state_offset + 2, 0);
965        if (clen > 0)        if (clen > 0)
966          {          {
967          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
968              (c < 256 &&              (c < 256 &&
969                (d != OP_ANY ||                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                (ims & PCRE_DOTALL) != 0 ||  
                ptr > end_subject - md->nllen ||  
                !IS_NEWLINE(ptr)  
               ) &&  
970                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
971            {            {
972              if (codevalue == OP_TYPEPOSSTAR)
973                {
974                active_count--;            /* Remove non-match possibility */
975                next_active_state--;
976                }
977            ADD_NEW(state_offset, 0);            ADD_NEW(state_offset, 0);
978            }            }
979          }          }
# Line 877  for (;;) Line 981  for (;;)
981    
982        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
983        case OP_TYPEEXACT:        case OP_TYPEEXACT:
984          count = current_state->count;  /* Number already matched */
985          if (clen > 0)
986            {
987            if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
988                (c < 256 &&
989                  (d != OP_ANY || !IS_NEWLINE(ptr)) &&
990                  ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
991              {
992              if (++count >= GET2(code, 1))
993                { ADD_NEW(state_offset + 4, 0); }
994              else
995                { ADD_NEW(state_offset, count); }
996              }
997            }
998          break;
999    
1000          /*-----------------------------------------------------------------*/
1001        case OP_TYPEUPTO:        case OP_TYPEUPTO:
1002        case OP_TYPEMINUPTO:        case OP_TYPEMINUPTO:
1003        if (codevalue != OP_TYPEEXACT)        case OP_TYPEPOSUPTO:
1004          { ADD_ACTIVE(state_offset + 4, 0); }        ADD_ACTIVE(state_offset + 4, 0);
1005        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1006        if (clen > 0)        if (clen > 0)
1007          {          {
1008          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||          if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
1009              (c < 256 &&              (c < 256 &&
1010                (d != OP_ANY ||                (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                (ims & PCRE_DOTALL) != 0 ||  
                ptr > end_subject - md->nllen ||  
                !IS_NEWLINE(ptr)  
               ) &&  
1011                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))                ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
1012            {            {
1013              if (codevalue == OP_TYPEPOSUPTO)
1014                {
1015                active_count--;           /* Remove non-match possibility */
1016                next_active_state--;
1017                }
1018            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1019              { ADD_NEW(state_offset + 4, 0); }              { ADD_NEW(state_offset + 4, 0); }
1020            else            else
# Line 903  for (;;) Line 1025  for (;;)
1025    
1026  /* ========================================================================== */  /* ========================================================================== */
1027        /* These are virtual opcodes that are used when something like        /* These are virtual opcodes that are used when something like
1028        OP_TYPEPLUS has OP_PROP, OP_NOTPROP, or OP_EXTUNI as its argument. It        OP_TYPEPLUS has OP_PROP, OP_NOTPROP, OP_ANYNL, or OP_EXTUNI as its
1029        keeps the code above fast for the other cases. The argument is in the        argument. It keeps the code above fast for the other cases. The argument
1030        d variable. */        is in the d variable. */
1031    
1032    #ifdef SUPPORT_UCP
1033        case OP_PROP_EXTRA + OP_TYPEPLUS:        case OP_PROP_EXTRA + OP_TYPEPLUS:
1034        case OP_PROP_EXTRA + OP_TYPEMINPLUS:        case OP_PROP_EXTRA + OP_TYPEMINPLUS:
1035          case OP_PROP_EXTRA + OP_TYPEPOSPLUS:
1036        count = current_state->count;           /* Already matched */        count = current_state->count;           /* Already matched */
1037        if (count > 0) { ADD_ACTIVE(state_offset + 4, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + 4, 0); }
1038        if (clen > 0)        if (clen > 0)
1039          {          {
1040          BOOL OK;          BOOL OK;
1041          int category = _pcre_ucp_findprop(c, &chartype, &script);          const ucd_record * prop = GET_UCD(c);
1042          switch(code[2])          switch(code[2])
1043            {            {
1044            case PT_ANY:            case PT_ANY:
# Line 922  for (;;) Line 1046  for (;;)
1046            break;            break;
1047    
1048            case PT_LAMP:            case PT_LAMP:
1049            OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt;
1050            break;            break;
1051    
1052            case PT_GC:            case PT_GC:
1053            OK = category == code[3];            OK = _pcre_ucp_gentype[prop->chartype] == code[3];
1054            break;            break;
1055    
1056            case PT_PC:            case PT_PC:
1057            OK = chartype == code[3];            OK = prop->chartype == code[3];
1058            break;            break;
1059    
1060            case PT_SC:            case PT_SC:
1061            OK = script == code[3];            OK = prop->script == code[3];
1062            break;            break;
1063    
1064            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
# Line 944  for (;;) Line 1068  for (;;)
1068            break;            break;
1069            }            }
1070    
1071          if (OK == (d == OP_PROP)) { count++; ADD_NEW(state_offset, count); }          if (OK == (d == OP_PROP))
1072              {
1073              if (count > 0 && codevalue == OP_PROP_EXTRA + OP_TYPEPOSPLUS)
1074                {
1075                active_count--;           /* Remove non-match possibility */
1076                next_active_state--;
1077                }
1078              count++;
1079              ADD_NEW(state_offset, count);
1080              }
1081          }          }
1082        break;        break;
1083    
1084        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1085        case OP_EXTUNI_EXTRA + OP_TYPEPLUS:        case OP_EXTUNI_EXTRA + OP_TYPEPLUS:
1086        case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS:        case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS:
1087          case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:
1088        count = current_state->count;  /* Already matched */        count = current_state->count;  /* Already matched */
1089        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1090        if (clen > 0 && _pcre_ucp_findprop(c, &chartype, &script) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1091          {          {
1092          const uschar *nptr = ptr + clen;          const uschar *nptr = ptr + clen;
1093          int ncount = 0;          int ncount = 0;
1094            if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)
1095              {
1096              active_count--;           /* Remove non-match possibility */
1097              next_active_state--;
1098              }
1099          while (nptr < end_subject)          while (nptr < end_subject)
1100            {            {
1101            int nd;            int nd;
1102            int ndlen = 1;            int ndlen = 1;
1103            GETCHARLEN(nd, nptr, ndlen);            GETCHARLEN(nd, nptr, ndlen);
1104            if (_pcre_ucp_findprop(nd, &chartype, &script) != ucp_M) break;            if (UCD_CATEGORY(nd) != ucp_M) break;
1105            ncount++;            ncount++;
1106            nptr += ndlen;            nptr += ndlen;
1107            }            }
# Line 970  for (;;) Line 1109  for (;;)
1109          ADD_NEW_DATA(-state_offset, count, ncount);          ADD_NEW_DATA(-state_offset, count, ncount);
1110          }          }
1111        break;        break;
1112    #endif
1113    
1114          /*-----------------------------------------------------------------*/
1115          case OP_ANYNL_EXTRA + OP_TYPEPLUS:
1116          case OP_ANYNL_EXTRA + OP_TYPEMINPLUS:
1117          case OP_ANYNL_EXTRA + OP_TYPEPOSPLUS:
1118          count = current_state->count;  /* Already matched */
1119          if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1120          if (clen > 0)
1121            {
1122            int ncount = 0;
1123            switch (c)
1124              {
1125              case 0x000b:
1126              case 0x000c:
1127              case 0x0085:
1128              case 0x2028:
1129              case 0x2029:
1130              if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1131              goto ANYNL01;
1132    
1133              case 0x000d:
1134              if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
1135              /* Fall through */
1136    
1137              ANYNL01:
1138              case 0x000a:
1139              if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)
1140                {
1141                active_count--;           /* Remove non-match possibility */
1142                next_active_state--;
1143                }
1144              count++;
1145              ADD_NEW_DATA(-state_offset, count, ncount);
1146              break;
1147    
1148              default:
1149              break;
1150              }
1151            }
1152          break;
1153    
1154        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1155          case OP_VSPACE_EXTRA + OP_TYPEPLUS:
1156          case OP_VSPACE_EXTRA + OP_TYPEMINPLUS:
1157          case OP_VSPACE_EXTRA + OP_TYPEPOSPLUS:
1158          count = current_state->count;  /* Already matched */
1159          if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1160          if (clen > 0)
1161            {
1162            BOOL OK;
1163            switch (c)
1164              {
1165              case 0x000a:
1166              case 0x000b:
1167              case 0x000c:
1168              case 0x000d:
1169              case 0x0085:
1170              case 0x2028:
1171              case 0x2029:
1172              OK = TRUE;
1173              break;
1174    
1175              default:
1176              OK = FALSE;
1177              break;
1178              }
1179    
1180            if (OK == (d == OP_VSPACE))
1181              {
1182              if (count > 0 && codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSPLUS)
1183                {
1184                active_count--;           /* Remove non-match possibility */
1185                next_active_state--;
1186                }
1187              count++;
1188              ADD_NEW_DATA(-state_offset, count, 0);
1189              }
1190            }
1191          break;
1192    
1193          /*-----------------------------------------------------------------*/
1194          case OP_HSPACE_EXTRA + OP_TYPEPLUS:
1195          case OP_HSPACE_EXTRA + OP_TYPEMINPLUS:
1196          case OP_HSPACE_EXTRA + OP_TYPEPOSPLUS:
1197          count = current_state->count;  /* Already matched */
1198          if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1199          if (clen > 0)
1200            {
1201            BOOL OK;
1202            switch (c)
1203              {
1204              case 0x09:      /* HT */
1205              case 0x20:      /* SPACE */
1206              case 0xa0:      /* NBSP */
1207              case 0x1680:    /* OGHAM SPACE MARK */
1208              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
1209              case 0x2000:    /* EN QUAD */
1210              case 0x2001:    /* EM QUAD */
1211              case 0x2002:    /* EN SPACE */
1212              case 0x2003:    /* EM SPACE */
1213              case 0x2004:    /* THREE-PER-EM SPACE */
1214              case 0x2005:    /* FOUR-PER-EM SPACE */
1215              case 0x2006:    /* SIX-PER-EM SPACE */
1216              case 0x2007:    /* FIGURE SPACE */
1217              case 0x2008:    /* PUNCTUATION SPACE */
1218              case 0x2009:    /* THIN SPACE */
1219              case 0x200A:    /* HAIR SPACE */
1220              case 0x202f:    /* NARROW NO-BREAK SPACE */
1221              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
1222              case 0x3000:    /* IDEOGRAPHIC SPACE */
1223              OK = TRUE;
1224              break;
1225    
1226              default:
1227              OK = FALSE;
1228              break;
1229              }
1230    
1231            if (OK == (d == OP_HSPACE))
1232              {
1233              if (count > 0 && codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSPLUS)
1234                {
1235                active_count--;           /* Remove non-match possibility */
1236                next_active_state--;
1237                }
1238              count++;
1239              ADD_NEW_DATA(-state_offset, count, 0);
1240              }
1241            }
1242          break;
1243    
1244          /*-----------------------------------------------------------------*/
1245    #ifdef SUPPORT_UCP
1246        case OP_PROP_EXTRA + OP_TYPEQUERY:        case OP_PROP_EXTRA + OP_TYPEQUERY:
1247        case OP_PROP_EXTRA + OP_TYPEMINQUERY:        case OP_PROP_EXTRA + OP_TYPEMINQUERY:
1248          case OP_PROP_EXTRA + OP_TYPEPOSQUERY:
1249        count = 4;        count = 4;
1250        goto QS1;        goto QS1;
1251    
1252        case OP_PROP_EXTRA + OP_TYPESTAR:        case OP_PROP_EXTRA + OP_TYPESTAR:
1253        case OP_PROP_EXTRA + OP_TYPEMINSTAR:        case OP_PROP_EXTRA + OP_TYPEMINSTAR:
1254          case OP_PROP_EXTRA + OP_TYPEPOSSTAR:
1255        count = 0;        count = 0;
1256    
1257        QS1:        QS1:
# Line 987  for (;;) Line 1260  for (;;)
1260        if (clen > 0)        if (clen > 0)
1261          {          {
1262          BOOL OK;          BOOL OK;
1263          int category = _pcre_ucp_findprop(c, &chartype, &script);          const ucd_record * prop = GET_UCD(c);
1264          switch(code[2])          switch(code[2])
1265            {            {
1266            case PT_ANY:            case PT_ANY:
# Line 995  for (;;) Line 1268  for (;;)
1268            break;            break;
1269    
1270            case PT_LAMP:            case PT_LAMP:
1271            OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt;
1272            break;            break;
1273    
1274            case PT_GC:            case PT_GC:
1275            OK = category == code[3];            OK = _pcre_ucp_gentype[prop->chartype] == code[3];
1276            break;            break;
1277    
1278            case PT_PC:            case PT_PC:
1279            OK = chartype == code[3];            OK = prop->chartype == code[3];
1280            break;            break;
1281    
1282            case PT_SC:            case PT_SC:
1283            OK = script == code[3];            OK = prop->script == code[3];
1284            break;            break;
1285    
1286            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
# Line 1017  for (;;) Line 1290  for (;;)
1290            break;            break;
1291            }            }
1292    
1293          if (OK == (d == OP_PROP)) { ADD_NEW(state_offset + count, 0); }          if (OK == (d == OP_PROP))
1294              {
1295              if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSSTAR ||
1296                  codevalue == OP_PROP_EXTRA + OP_TYPEPOSQUERY)
1297                {
1298                active_count--;           /* Remove non-match possibility */
1299                next_active_state--;
1300                }
1301              ADD_NEW(state_offset + count, 0);
1302              }
1303          }          }
1304        break;        break;
1305    
1306        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1307        case OP_EXTUNI_EXTRA + OP_TYPEQUERY:        case OP_EXTUNI_EXTRA + OP_TYPEQUERY:
1308        case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY:        case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY:
1309          case OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY:
1310        count = 2;        count = 2;
1311        goto QS2;        goto QS2;
1312    
1313        case OP_EXTUNI_EXTRA + OP_TYPESTAR:        case OP_EXTUNI_EXTRA + OP_TYPESTAR:
1314        case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR:        case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR:
1315          case OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR:
1316        count = 0;        count = 0;
1317    
1318        QS2:        QS2:
1319    
1320        ADD_ACTIVE(state_offset + 2, 0);        ADD_ACTIVE(state_offset + 2, 0);
1321        if (clen > 0 && _pcre_ucp_findprop(c, &chartype, &script) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1322          {          {
1323          const uschar *nptr = ptr + clen;          const uschar *nptr = ptr + clen;
1324          int ncount = 0;          int ncount = 0;
1325            if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||
1326                codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)
1327              {
1328              active_count--;           /* Remove non-match possibility */
1329              next_active_state--;
1330              }
1331          while (nptr < end_subject)          while (nptr < end_subject)
1332            {            {
1333            int nd;            int nd;
1334            int ndlen = 1;            int ndlen = 1;
1335            GETCHARLEN(nd, nptr, ndlen);            GETCHARLEN(nd, nptr, ndlen);
1336            if (_pcre_ucp_findprop(nd, &chartype, &script) != ucp_M) break;            if (UCD_CATEGORY(nd) != ucp_M) break;
1337            ncount++;            ncount++;
1338            nptr += ndlen;            nptr += ndlen;
1339            }            }
1340          ADD_NEW_DATA(-(state_offset + count), 0, ncount);          ADD_NEW_DATA(-(state_offset + count), 0, ncount);
1341          }          }
1342        break;        break;
1343    #endif
1344    
1345          /*-----------------------------------------------------------------*/
1346          case OP_ANYNL_EXTRA + OP_TYPEQUERY:
1347          case OP_ANYNL_EXTRA + OP_TYPEMINQUERY:
1348          case OP_ANYNL_EXTRA + OP_TYPEPOSQUERY:
1349          count = 2;
1350          goto QS3;
1351    
1352          case OP_ANYNL_EXTRA + OP_TYPESTAR:
1353          case OP_ANYNL_EXTRA + OP_TYPEMINSTAR:
1354          case OP_ANYNL_EXTRA + OP_TYPEPOSSTAR:
1355          count = 0;
1356    
1357          QS3:
1358          ADD_ACTIVE(state_offset + 2, 0);
1359          if (clen > 0)
1360            {
1361            int ncount = 0;
1362            switch (c)
1363              {
1364              case 0x000b:
1365              case 0x000c:
1366              case 0x0085:
1367              case 0x2028:
1368              case 0x2029:
1369              if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1370              goto ANYNL02;
1371    
1372              case 0x000d:
1373              if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
1374              /* Fall through */
1375    
1376              ANYNL02:
1377              case 0x000a:
1378              if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||
1379                  codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)
1380                {
1381                active_count--;           /* Remove non-match possibility */
1382                next_active_state--;
1383                }
1384              ADD_NEW_DATA(-(state_offset + count), 0, ncount);
1385              break;
1386    
1387              default:
1388              break;
1389              }
1390            }
1391          break;
1392    
1393          /*-----------------------------------------------------------------*/
1394          case OP_VSPACE_EXTRA + OP_TYPEQUERY:
1395          case OP_VSPACE_EXTRA + OP_TYPEMINQUERY:
1396          case OP_VSPACE_EXTRA + OP_TYPEPOSQUERY:
1397          count = 2;
1398          goto QS4;
1399    
1400          case OP_VSPACE_EXTRA + OP_TYPESTAR:
1401          case OP_VSPACE_EXTRA + OP_TYPEMINSTAR:
1402          case OP_VSPACE_EXTRA + OP_TYPEPOSSTAR:
1403          count = 0;
1404    
1405          QS4:
1406          ADD_ACTIVE(state_offset + 2, 0);
1407          if (clen > 0)
1408            {
1409            BOOL OK;
1410            switch (c)
1411              {
1412              case 0x000a:
1413              case 0x000b:
1414              case 0x000c:
1415              case 0x000d:
1416              case 0x0085:
1417              case 0x2028:
1418              case 0x2029:
1419              OK = TRUE;
1420              break;
1421    
1422              default:
1423              OK = FALSE;
1424              break;
1425              }
1426            if (OK == (d == OP_VSPACE))
1427              {
1428              if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSSTAR ||
1429                  codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSQUERY)
1430                {
1431                active_count--;           /* Remove non-match possibility */
1432                next_active_state--;
1433                }
1434              ADD_NEW_DATA(-(state_offset + count), 0, 0);
1435              }
1436            }
1437          break;
1438    
1439          /*-----------------------------------------------------------------*/
1440          case OP_HSPACE_EXTRA + OP_TYPEQUERY:
1441          case OP_HSPACE_EXTRA + OP_TYPEMINQUERY:
1442          case OP_HSPACE_EXTRA + OP_TYPEPOSQUERY:
1443          count = 2;
1444          goto QS5;
1445    
1446          case OP_HSPACE_EXTRA + OP_TYPESTAR:
1447          case OP_HSPACE_EXTRA + OP_TYPEMINSTAR:
1448          case OP_HSPACE_EXTRA + OP_TYPEPOSSTAR:
1449          count = 0;
1450    
1451          QS5:
1452          ADD_ACTIVE(state_offset + 2, 0);
1453          if (clen > 0)
1454            {
1455            BOOL OK;
1456            switch (c)
1457              {
1458              case 0x09:      /* HT */
1459              case 0x20:      /* SPACE */
1460              case 0xa0:      /* NBSP */
1461              case 0x1680:    /* OGHAM SPACE MARK */
1462              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
1463              case 0x2000:    /* EN QUAD */
1464              case 0x2001:    /* EM QUAD */
1465              case 0x2002:    /* EN SPACE */
1466              case 0x2003:    /* EM SPACE */
1467              case 0x2004:    /* THREE-PER-EM SPACE */
1468              case 0x2005:    /* FOUR-PER-EM SPACE */
1469              case 0x2006:    /* SIX-PER-EM SPACE */
1470              case 0x2007:    /* FIGURE SPACE */
1471              case 0x2008:    /* PUNCTUATION SPACE */
1472              case 0x2009:    /* THIN SPACE */
1473              case 0x200A:    /* HAIR SPACE */
1474              case 0x202f:    /* NARROW NO-BREAK SPACE */
1475              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
1476              case 0x3000:    /* IDEOGRAPHIC SPACE */
1477              OK = TRUE;
1478              break;
1479    
1480              default:
1481              OK = FALSE;
1482              break;
1483              }
1484    
1485            if (OK == (d == OP_HSPACE))
1486              {
1487              if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSSTAR ||
1488                  codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSQUERY)
1489                {
1490                active_count--;           /* Remove non-match possibility */
1491                next_active_state--;
1492                }
1493              ADD_NEW_DATA(-(state_offset + count), 0, 0);
1494              }
1495            }
1496          break;
1497    
1498        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1499    #ifdef SUPPORT_UCP
1500        case OP_PROP_EXTRA + OP_TYPEEXACT:        case OP_PROP_EXTRA + OP_TYPEEXACT:
1501        case OP_PROP_EXTRA + OP_TYPEUPTO:        case OP_PROP_EXTRA + OP_TYPEUPTO:
1502        case OP_PROP_EXTRA + OP_TYPEMINUPTO:        case OP_PROP_EXTRA + OP_TYPEMINUPTO:
1503          case OP_PROP_EXTRA + OP_TYPEPOSUPTO:
1504        if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)
1505          { ADD_ACTIVE(state_offset + 6, 0); }          { ADD_ACTIVE(state_offset + 6, 0); }
1506        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1507        if (clen > 0)        if (clen > 0)
1508          {          {
1509          BOOL OK;          BOOL OK;
1510          int category = _pcre_ucp_findprop(c, &chartype, &script);          const ucd_record * prop = GET_UCD(c);
1511          switch(code[4])          switch(code[4])
1512            {            {
1513            case PT_ANY:            case PT_ANY:
# Line 1069  for (;;) Line 1515  for (;;)
1515            break;            break;
1516    
1517            case PT_LAMP:            case PT_LAMP:
1518            OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;            OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt;
1519            break;            break;
1520    
1521            case PT_GC:            case PT_GC:
1522            OK = category == code[5];            OK = _pcre_ucp_gentype[prop->chartype] == code[5];
1523            break;            break;
1524    
1525            case PT_PC:            case PT_PC:
1526            OK = chartype == code[5];            OK = prop->chartype == code[5];
1527            break;            break;
1528    
1529            case PT_SC:            case PT_SC:
1530            OK = script == code[5];            OK = prop->script == code[5];
1531            break;            break;
1532    
1533            /* Should never occur, but keep compilers from grumbling. */            /* Should never occur, but keep compilers from grumbling. */
# Line 1093  for (;;) Line 1539  for (;;)
1539    
1540          if (OK == (d == OP_PROP))          if (OK == (d == OP_PROP))
1541            {            {
1542              if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSUPTO)
1543                {
1544                active_count--;           /* Remove non-match possibility */
1545                next_active_state--;
1546                }
1547            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
1548              { ADD_NEW(state_offset + 6, 0); }              { ADD_NEW(state_offset + 6, 0); }
1549            else            else
# Line 1105  for (;;) Line 1556  for (;;)
1556        case OP_EXTUNI_EXTRA + OP_TYPEEXACT:        case OP_EXTUNI_EXTRA + OP_TYPEEXACT:
1557        case OP_EXTUNI_EXTRA + OP_TYPEUPTO:        case OP_EXTUNI_EXTRA + OP_TYPEUPTO:
1558        case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:        case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:
1559          case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:
1560        if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)        if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)
1561          { ADD_ACTIVE(state_offset + 4, 0); }          { ADD_ACTIVE(state_offset + 4, 0); }
1562        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
1563        if (clen > 0 && _pcre_ucp_findprop(c, &chartype, &script) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1564          {          {
1565          const uschar *nptr = ptr + clen;          const uschar *nptr = ptr + clen;
1566          int ncount = 0;          int ncount = 0;
1567            if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)
1568              {
1569              active_count--;           /* Remove non-match possibility */
1570              next_active_state--;
1571              }
1572          while (nptr < end_subject)          while (nptr < end_subject)
1573            {            {
1574            int nd;            int nd;
1575            int ndlen = 1;            int ndlen = 1;
1576            GETCHARLEN(nd, nptr, ndlen);            GETCHARLEN(nd, nptr, ndlen);
1577            if (_pcre_ucp_findprop(nd, &chartype, &script) != ucp_M) break;            if (UCD_CATEGORY(nd) != ucp_M) break;
1578            ncount++;            ncount++;
1579            nptr += ndlen;            nptr += ndlen;
1580            }            }
# Line 1127  for (;;) Line 1584  for (;;)
1584            { ADD_NEW_DATA(-state_offset, count, ncount); }            { ADD_NEW_DATA(-state_offset, count, ncount); }
1585          }          }
1586        break;        break;
1587    #endif
1588    
1589          /*-----------------------------------------------------------------*/
1590          case OP_ANYNL_EXTRA + OP_TYPEEXACT:
1591          case OP_ANYNL_EXTRA + OP_TYPEUPTO:
1592          case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:
1593          case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:
1594          if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)
1595            { ADD_ACTIVE(state_offset + 4, 0); }
1596          count = current_state->count;  /* Number already matched */
1597          if (clen > 0)
1598            {
1599            int ncount = 0;
1600            switch (c)
1601              {
1602              case 0x000b:
1603              case 0x000c:
1604              case 0x0085:
1605              case 0x2028:
1606              case 0x2029:
1607              if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1608              goto ANYNL03;
1609    
1610              case 0x000d:
1611              if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
1612              /* Fall through */
1613    
1614              ANYNL03:
1615              case 0x000a:
1616              if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)
1617                {
1618                active_count--;           /* Remove non-match possibility */
1619                next_active_state--;
1620                }
1621              if (++count >= GET2(code, 1))
1622                { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }
1623              else
1624                { ADD_NEW_DATA(-state_offset, count, ncount); }
1625              break;
1626    
1627              default:
1628              break;
1629              }
1630            }
1631          break;
1632    
1633          /*-----------------------------------------------------------------*/
1634          case OP_VSPACE_EXTRA + OP_TYPEEXACT:
1635          case OP_VSPACE_EXTRA + OP_TYPEUPTO:
1636          case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:
1637          case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:
1638          if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)
1639            { ADD_ACTIVE(state_offset + 4, 0); }
1640          count = current_state->count;  /* Number already matched */
1641          if (clen > 0)
1642            {
1643            BOOL OK;
1644            switch (c)
1645              {
1646              case 0x000a:
1647              case 0x000b:
1648              case 0x000c:
1649              case 0x000d:
1650              case 0x0085:
1651              case 0x2028:
1652              case 0x2029:
1653              OK = TRUE;
1654              break;
1655    
1656              default:
1657              OK = FALSE;
1658              }
1659    
1660            if (OK == (d == OP_VSPACE))
1661              {
1662              if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSUPTO)
1663                {
1664                active_count--;           /* Remove non-match possibility */
1665                next_active_state--;
1666                }
1667              if (++count >= GET2(code, 1))
1668                { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }
1669              else
1670                { ADD_NEW_DATA(-state_offset, count, 0); }
1671              }
1672            }
1673          break;
1674    
1675          /*-----------------------------------------------------------------*/
1676          case OP_HSPACE_EXTRA + OP_TYPEEXACT:
1677          case OP_HSPACE_EXTRA + OP_TYPEUPTO:
1678          case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:
1679          case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:
1680          if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)
1681            { ADD_ACTIVE(state_offset + 4, 0); }
1682          count = current_state->count;  /* Number already matched */
1683          if (clen > 0)
1684            {
1685            BOOL OK;
1686            switch (c)
1687              {
1688              case 0x09:      /* HT */
1689              case 0x20:      /* SPACE */
1690              case 0xa0:      /* NBSP */
1691              case 0x1680:    /* OGHAM SPACE MARK */
1692              case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
1693              case 0x2000:    /* EN QUAD */
1694              case 0x2001:    /* EM QUAD */
1695              case 0x2002:    /* EN SPACE */
1696              case 0x2003:    /* EM SPACE */
1697              case 0x2004:    /* THREE-PER-EM SPACE */
1698              case 0x2005:    /* FOUR-PER-EM SPACE */
1699              case 0x2006:    /* SIX-PER-EM SPACE */
1700              case 0x2007:    /* FIGURE SPACE */
1701              case 0x2008:    /* PUNCTUATION SPACE */
1702              case 0x2009:    /* THIN SPACE */
1703              case 0x200A:    /* HAIR SPACE */
1704              case 0x202f:    /* NARROW NO-BREAK SPACE */
1705              case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
1706              case 0x3000:    /* IDEOGRAPHIC SPACE */
1707              OK = TRUE;
1708              break;
1709    
1710              default:
1711              OK = FALSE;
1712              break;
1713              }
1714    
1715            if (OK == (d == OP_HSPACE))
1716              {
1717              if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSUPTO)
1718                {
1719                active_count--;           /* Remove non-match possibility */
1720                next_active_state--;
1721                }
1722              if (++count >= GET2(code, 1))
1723                { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }
1724              else
1725                { ADD_NEW_DATA(-state_offset, count, 0); }
1726              }
1727            }
1728          break;
1729    
1730  /* ========================================================================== */  /* ========================================================================== */
1731        /* These opcodes are followed by a character that is usually compared        /* These opcodes are followed by a character that is usually compared
# Line 1148  for (;;) Line 1747  for (;;)
1747          {          {
1748          if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else          if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else
1749            {            {
1750            int othercase;            unsigned int othercase;
1751            if (c < 128) othercase = fcc[c]; else            if (c < 128) othercase = fcc[c]; else
1752    
1753            /* If we have Unicode property support, we can use it to test the            /* If we have Unicode property support, we can use it to test the
1754            other case of the character. */            other case of the character. */
1755    
1756  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
1757            othercase = _pcre_ucp_othercase(c);            othercase = UCD_OTHERCASE(c);
1758  #else  #else
1759            othercase = -1;            othercase = NOTACHAR;
1760  #endif  #endif
1761    
1762            if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }            if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }
# Line 1180  for (;;) Line 1779  for (;;)
1779        to wait for them to pass before continuing. */        to wait for them to pass before continuing. */
1780    
1781        case OP_EXTUNI:        case OP_EXTUNI:
1782        if (clen > 0 && _pcre_ucp_findprop(c, &chartype, &script) != ucp_M)        if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1783          {          {
1784          const uschar *nptr = ptr + clen;          const uschar *nptr = ptr + clen;
1785          int ncount = 0;          int ncount = 0;
# Line 1188  for (;;) Line 1787  for (;;)
1787            {            {
1788            int nclen = 1;            int nclen = 1;
1789            GETCHARLEN(c, nptr, nclen);            GETCHARLEN(c, nptr, nclen);
1790            if (_pcre_ucp_findprop(c, &chartype, &script) != ucp_M) break;            if (UCD_CATEGORY(c) != ucp_M) break;
1791            ncount++;            ncount++;
1792            nptr += nclen;            nptr += nclen;
1793            }            }
# Line 1198  for (;;) Line 1797  for (;;)
1797  #endif  #endif
1798    
1799        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1800          /* This is a tricky like EXTUNI because it too can match more than one
1801          character (when CR is followed by LF). In this case, set up a negative
1802          state to wait for one character to pass before continuing. */
1803    
1804          case OP_ANYNL:
1805          if (clen > 0) switch(c)
1806            {
1807            case 0x000b:
1808            case 0x000c:
1809            case 0x0085:
1810            case 0x2028:
1811            case 0x2029:
1812            if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
1813    
1814            case 0x000a:
1815            ADD_NEW(state_offset + 1, 0);
1816            break;
1817    
1818            case 0x000d:
1819            if (ptr + 1 < end_subject && ptr[1] == 0x0a)
1820              {
1821              ADD_NEW_DATA(-(state_offset + 1), 0, 1);
1822              }
1823            else
1824              {
1825              ADD_NEW(state_offset + 1, 0);
1826              }
1827            break;
1828            }
1829          break;
1830    
1831          /*-----------------------------------------------------------------*/
1832          case OP_NOT_VSPACE:
1833          if (clen > 0) switch(c)
1834            {
1835            case 0x000a:
1836            case 0x000b:
1837            case 0x000c:
1838            case 0x000d:
1839            case 0x0085:
1840            case 0x2028:
1841            case 0x2029:
1842            break;
1843    
1844            default:
1845            ADD_NEW(state_offset + 1, 0);
1846            break;
1847            }
1848          break;
1849    
1850          /*-----------------------------------------------------------------*/
1851          case OP_VSPACE:
1852          if (clen > 0) switch(c)
1853            {
1854            case 0x000a:
1855            case 0x000b:
1856            case 0x000c:
1857            case 0x000d:
1858            case 0x0085:
1859            case 0x2028:
1860            case 0x2029:
1861            ADD_NEW(state_offset + 1, 0);
1862            break;
1863    
1864            default: break;
1865            }
1866          break;
1867    
1868          /*-----------------------------------------------------------------*/
1869          case OP_NOT_HSPACE:
1870          if (clen > 0) switch(c)
1871            {
1872            case 0x09:      /* HT */
1873            case 0x20:      /* SPACE */
1874            case 0xa0:      /* NBSP */
1875            case 0x1680:    /* OGHAM SPACE MARK */
1876            case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
1877            case 0x2000:    /* EN QUAD */
1878            case 0x2001:    /* EM QUAD */
1879            case 0x2002:    /* EN SPACE */
1880            case 0x2003:    /* EM SPACE */
1881            case 0x2004:    /* THREE-PER-EM SPACE */
1882            case 0x2005:    /* FOUR-PER-EM SPACE */
1883            case 0x2006:    /* SIX-PER-EM SPACE */
1884            case 0x2007:    /* FIGURE SPACE */
1885            case 0x2008:    /* PUNCTUATION SPACE */
1886            case 0x2009:    /* THIN SPACE */
1887            case 0x200A:    /* HAIR SPACE */
1888            case 0x202f:    /* NARROW NO-BREAK SPACE */
1889            case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
1890            case 0x3000:    /* IDEOGRAPHIC SPACE */
1891            break;
1892    
1893            default:
1894            ADD_NEW(state_offset + 1, 0);
1895            break;
1896            }
1897          break;
1898    
1899          /*-----------------------------------------------------------------*/
1900          case OP_HSPACE:
1901          if (clen > 0) switch(c)
1902            {
1903            case 0x09:      /* HT */
1904            case 0x20:      /* SPACE */
1905            case 0xa0:      /* NBSP */
1906            case 0x1680:    /* OGHAM SPACE MARK */
1907            case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
1908            case 0x2000:    /* EN QUAD */
1909            case 0x2001:    /* EM QUAD */
1910            case 0x2002:    /* EN SPACE */
1911            case 0x2003:    /* EM SPACE */
1912            case 0x2004:    /* THREE-PER-EM SPACE */
1913            case 0x2005:    /* FOUR-PER-EM SPACE */
1914            case 0x2006:    /* SIX-PER-EM SPACE */
1915            case 0x2007:    /* FIGURE SPACE */
1916            case 0x2008:    /* PUNCTUATION SPACE */
1917            case 0x2009:    /* THIN SPACE */
1918            case 0x200A:    /* HAIR SPACE */
1919            case 0x202f:    /* NARROW NO-BREAK SPACE */
1920            case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
1921            case 0x3000:    /* IDEOGRAPHIC SPACE */
1922            ADD_NEW(state_offset + 1, 0);
1923            break;
1924            }
1925          break;
1926    
1927          /*-----------------------------------------------------------------*/
1928        /* Match a negated single character. This is only used for one-byte        /* Match a negated single character. This is only used for one-byte
1929        characters, that is, we know that d < 256. The character we are        characters, that is, we know that d < 256. The character we are
1930        checking (c) can be multibyte. */        checking (c) can be multibyte. */
# Line 1205  for (;;) Line 1932  for (;;)
1932        case OP_NOT:        case OP_NOT:
1933        if (clen > 0)        if (clen > 0)
1934          {          {
1935          int otherd = ((ims & PCRE_CASELESS) != 0)? fcc[d] : d;          unsigned int otherd = ((ims & PCRE_CASELESS) != 0)? fcc[d] : d;
1936          if (c != d && c != otherd) { ADD_NEW(state_offset + dlen + 1, 0); }          if (c != d && c != otherd) { ADD_NEW(state_offset + dlen + 1, 0); }
1937          }          }
1938        break;        break;
# Line 1213  for (;;) Line 1940  for (;;)
1940        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1941        case OP_PLUS:        case OP_PLUS:
1942        case OP_MINPLUS:        case OP_MINPLUS:
1943          case OP_POSPLUS:
1944        case OP_NOTPLUS:        case OP_NOTPLUS:
1945        case OP_NOTMINPLUS:        case OP_NOTMINPLUS:
1946          case OP_NOTPOSPLUS:
1947        count = current_state->count;  /* Already matched */        count = current_state->count;  /* Already matched */
1948        if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }        if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }
1949        if (clen > 0)        if (clen > 0)
1950          {          {
1951          int otherd = -1;          unsigned int otherd = NOTACHAR;
1952          if ((ims & PCRE_CASELESS) != 0)          if ((ims & PCRE_CASELESS) != 0)
1953            {            {
1954  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
1955            if (utf8 && d >= 128)            if (utf8 && d >= 128)
1956              {              {
1957  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
1958              otherd = _pcre_ucp_othercase(d);              otherd = UCD_OTHERCASE(d);
1959  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
1960              }              }
1961            else            else
# Line 1234  for (;;) Line 1963  for (;;)
1963            otherd = fcc[d];            otherd = fcc[d];
1964            }            }
1965          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
1966            { count++; ADD_NEW(state_offset, count); }            {
1967              if (count > 0 &&
1968                  (codevalue == OP_POSPLUS || codevalue == OP_NOTPOSPLUS))
1969                {
1970                active_count--;             /* Remove non-match possibility */
1971                next_active_state--;
1972                }
1973              count++;
1974              ADD_NEW(state_offset, count);
1975              }
1976          }          }
1977        break;        break;
1978    
1979        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
1980        case OP_QUERY:        case OP_QUERY:
1981        case OP_MINQUERY:        case OP_MINQUERY:
1982          case OP_POSQUERY:
1983        case OP_NOTQUERY:        case OP_NOTQUERY:
1984        case OP_NOTMINQUERY:        case OP_NOTMINQUERY:
1985          case OP_NOTPOSQUERY:
1986        ADD_ACTIVE(state_offset + dlen + 1, 0);        ADD_ACTIVE(state_offset + dlen + 1, 0);
1987        if (clen > 0)        if (clen > 0)
1988          {          {
1989          int otherd = -1;          unsigned int otherd = NOTACHAR;
1990          if ((ims & PCRE_CASELESS) != 0)          if ((ims & PCRE_CASELESS) != 0)
1991            {            {
1992  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
1993            if (utf8 && d >= 128)            if (utf8 && d >= 128)
1994              {              {
1995  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
1996              otherd = _pcre_ucp_othercase(d);              otherd = UCD_OTHERCASE(d);
1997  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
1998              }              }
1999            else            else
# Line 1261  for (;;) Line 2001  for (;;)
2001            otherd = fcc[d];            otherd = fcc[d];
2002            }            }
2003          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2004            { ADD_NEW(state_offset + dlen + 1, 0); }            {
2005              if (codevalue == OP_POSQUERY || codevalue == OP_NOTPOSQUERY)
2006                {
2007                active_count--;            /* Remove non-match possibility */
2008                next_active_state--;
2009                }
2010              ADD_NEW(state_offset + dlen + 1, 0);
2011              }
2012          }          }
2013        break;        break;
2014    
2015        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2016        case OP_STAR:        case OP_STAR:
2017        case OP_MINSTAR:        case OP_MINSTAR:
2018          case OP_POSSTAR:
2019        case OP_NOTSTAR:        case OP_NOTSTAR:
2020        case OP_NOTMINSTAR:        case OP_NOTMINSTAR:
2021          case OP_NOTPOSSTAR:
2022        ADD_ACTIVE(state_offset + dlen + 1, 0);        ADD_ACTIVE(state_offset + dlen + 1, 0);
2023        if (clen > 0)        if (clen > 0)
2024          {          {
2025          int otherd = -1;          unsigned int otherd = NOTACHAR;
2026          if ((ims & PCRE_CASELESS) != 0)          if ((ims & PCRE_CASELESS) != 0)
2027            {            {
2028  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
2029            if (utf8 && d >= 128)            if (utf8 && d >= 128)
2030              {              {
2031  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2032              otherd = _pcre_ucp_othercase(d);              otherd = UCD_OTHERCASE(d);
2033  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2034              }              }
2035            else            else
# Line 1288  for (;;) Line 2037  for (;;)
2037            otherd = fcc[d];            otherd = fcc[d];
2038            }            }
2039          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2040            { ADD_NEW(state_offset, 0); }            {
2041              if (codevalue == OP_POSSTAR || codevalue == OP_NOTPOSSTAR)
2042                {
2043                active_count--;            /* Remove non-match possibility */
2044                next_active_state--;
2045                }
2046              ADD_NEW(state_offset, 0);
2047              }
2048          }          }
2049        break;        break;
2050    
2051        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2052        case OP_EXACT:        case OP_EXACT:
2053          case OP_NOTEXACT:
2054          count = current_state->count;  /* Number already matched */
2055          if (clen > 0)
2056            {
2057            unsigned int otherd = NOTACHAR;
2058            if ((ims & PCRE_CASELESS) != 0)
2059              {
2060    #ifdef SUPPORT_UTF8
2061              if (utf8 && d >= 128)
2062                {
2063    #ifdef SUPPORT_UCP
2064                otherd = UCD_OTHERCASE(d);
2065    #endif  /* SUPPORT_UCP */
2066                }
2067              else
2068    #endif  /* SUPPORT_UTF8 */
2069              otherd = fcc[d];
2070              }
2071            if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2072              {
2073              if (++count >= GET2(code, 1))
2074                { ADD_NEW(state_offset + dlen + 3, 0); }
2075              else
2076                { ADD_NEW(state_offset, count); }
2077              }
2078            }
2079          break;
2080    
2081          /*-----------------------------------------------------------------*/
2082        case OP_UPTO:        case OP_UPTO:
2083        case OP_MINUPTO:        case OP_MINUPTO:
2084        case OP_NOTEXACT:        case OP_POSUPTO:
2085        case OP_NOTUPTO:        case OP_NOTUPTO:
2086        case OP_NOTMINUPTO:        case OP_NOTMINUPTO:
2087        if (codevalue != OP_EXACT && codevalue != OP_NOTEXACT)        case OP_NOTPOSUPTO:
2088          { ADD_ACTIVE(state_offset + dlen + 3, 0); }        ADD_ACTIVE(state_offset + dlen + 3, 0);
2089        count = current_state->count;  /* Number already matched */        count = current_state->count;  /* Number already matched */
2090        if (clen > 0)        if (clen > 0)
2091          {          {
2092          int otherd = -1;          unsigned int otherd = NOTACHAR;
2093          if ((ims & PCRE_CASELESS) != 0)          if ((ims & PCRE_CASELESS) != 0)
2094            {            {
2095  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
2096            if (utf8 && d >= 128)            if (utf8 && d >= 128)
2097              {              {
2098  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2099              otherd = _pcre_ucp_othercase(d);              otherd = UCD_OTHERCASE(d);
2100  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2101              }              }
2102            else            else
# Line 1320  for (;;) Line 2105  for (;;)
2105            }            }
2106          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))          if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
2107            {            {
2108              if (codevalue == OP_POSUPTO || codevalue == OP_NOTPOSUPTO)
2109                {
2110                active_count--;             /* Remove non-match possibility */
2111                next_active_state--;
2112                }
2113            if (++count >= GET2(code, 1))            if (++count >= GET2(code, 1))
2114              { ADD_NEW(state_offset + dlen + 3, 0); }              { ADD_NEW(state_offset + dlen + 3, 0); }
2115            else            else
# Line 1414  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. */        to use recursion in order to handle them. The "always failing" assertion
2208          (?!) is optimised to OP_FAIL when compiling, so we have to support that,
2209          though the other "backtracking verbs" are not supported. */
2210    
2211          case OP_FAIL:
2212          forced_fail++;    /* Count FAILs for multiple states */
2213          break;
2214    
2215        case OP_ASSERT:        case OP_ASSERT:
2216        case OP_ASSERT_NOT:        case OP_ASSERT_NOT:
# Line 1448  for (;;) Line 2244  for (;;)
2244    
2245        /*-----------------------------------------------------------------*/        /*-----------------------------------------------------------------*/
2246        case OP_COND:        case OP_COND:
2247          case OP_SCOND:
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          /* The only supported version of OP_CREF is for the value 0xffff, which          /* Because of the way auto-callout works during compile, a callout item
2255          means "test if in a recursion". */          is inserted between OP_COND and an assertion condition. This does not
2256            happen for the other conditions. */
2257    
2258          if (condcode == OP_CREF)          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 */
2285    
2286            if (condcode == OP_CREF) return PCRE_ERROR_DFA_UCOND;
2287    
2288            /* The DEFINE condition is always false */
2289    
2290            if (condcode == OP_DEF)
2291              { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
2292    
2293            /* 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
2295            recursed groups. */
2296    
2297            else if (condcode == OP_RREF)
2298            {            {
2299            int value = GET2(code, LINK_SIZE+2);            int value = GET2(code, LINK_SIZE+2);
2300            if (value != 0xffff) 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 1491  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 1643  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 1660  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 1677  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 1728  is not anchored. Line 2578  is not anchored.
2578    
2579  Arguments:  Arguments:
2580    argument_re     points to the compiled expression    argument_re     points to the compiled expression
2581    extra_data      points to extra data or is NULL (not currently used)    extra_data      points to extra data or is NULL
2582    subject         points to the subject string    subject         points to the subject string
2583    length          length of subject string (may contain binary zeros)    length          length of subject string (may contain binary zeros)
2584    start_offset    where to start in the subject string    start_offset    where to start in the subject string
# Line 1744  Returns:          > 0 => number of match Line 2594  Returns:          > 0 => number of match
2594                   < -1 => some kind of unexpected problem                   < -1 => some kind of unexpected problem
2595  */  */
2596    
2597  PCRE_DATA_SCOPE int  PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
2598  pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,  pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,
2599    const char *subject, int length, int start_offset, int options, int *offsets,    const char *subject, int length, int start_offset, int options, int *offsets,
2600    int offsetcount, int *workspace, int wscount)    int offsetcount, int *workspace, int wscount)
# Line 1834  md->end_subject = end_subject; Line 2684  md->end_subject = end_subject;
2684  md->moptions = options;  md->moptions = options;
2685  md->poptions = re->options;  md->poptions = re->options;
2686    
2687  /* Handle different types of newline. The two bits give four cases. If nothing  /* If the BSR option is not set at match time, copy what was set
2688  is set at run time, whatever was used at compile time applies. */  at compile time. */
2689    
2690    if ((md->moptions & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == 0)
2691      {
2692      if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0)
2693        md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE);
2694    #ifdef BSR_ANYCRLF
2695      else md->moptions |= PCRE_BSR_ANYCRLF;
2696    #endif
2697      }
2698    
2699    /* Handle different types of newline. The three bits give eight cases. If
2700    nothing is set at run time, whatever was used at compile time applies. */
2701    
2702  switch ((((options & PCRE_NEWLINE_CRLF) == 0)? re->options : options) &  switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) &
2703           PCRE_NEWLINE_CRLF)           PCRE_NEWLINE_BITS)
2704    {    {
2705    default:              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;
2711      case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
2712      default: return PCRE_ERROR_BADNEWLINE;
2713    }    }
2714    
2715  if (newline > 255)  if (newline == -2)
2716    {    {
2717    md->nllen = 2;    md->nltype = NLTYPE_ANYCRLF;
2718    md->nl[0] = (newline >> 8) & 255;    }
2719    md->nl[1] = newline & 255;  else if (newline < 0)
2720      {
2721      md->nltype = NLTYPE_ANY;
2722    }    }
2723  else  else
2724    {    {
2725    md->nllen = 1;    md->nltype = NLTYPE_FIXED;
2726    md->nl[0] = newline;    if (newline > 255)
2727        {
2728        md->nllen = 2;
2729        md->nl[0] = (newline >> 8) & 255;
2730        md->nl[1] = newline & 255;
2731        }
2732      else
2733        {
2734        md->nllen = 1;
2735        md->nl[0] = newline;
2736        }
2737    }    }
2738    
2739  /* Check a UTF-8 string if required. Unfortunately there's no way of passing  /* Check a UTF-8 string if required. Unfortunately there's no way of passing
# Line 1889  if (md->tables == NULL) md->tables = _pc Line 2766  if (md->tables == NULL) md->tables = _pc
2766  used in a loop when finding where to start. */  used in a loop when finding where to start. */
2767    
2768  lcc = md->tables + lcc_offset;  lcc = md->tables + lcc_offset;
2769  startline = (re->options & PCRE_STARTLINE) != 0;  startline = (re->flags & PCRE_STARTLINE) != 0;
2770  firstline = (re->options & PCRE_FIRSTLINE) != 0;  firstline = (re->options & PCRE_FIRSTLINE) != 0;
2771    
2772  /* Set up the first character to match, if available. The first_byte value is  /* Set up the first character to match, if available. The first_byte value is
# Line 1900  studied, there may be a bitmap of possib Line 2777  studied, there may be a bitmap of possib
2777    
2778  if (!anchored)  if (!anchored)
2779    {    {
2780    if ((re->options & PCRE_FIRSTSET) != 0)    if ((re->flags & PCRE_FIRSTSET) != 0)
2781      {      {
2782      first_byte = re->first_byte & 255;      first_byte = re->first_byte & 255;
2783      if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)      if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)
# Line 1917  if (!anchored) Line 2794  if (!anchored)
2794  /* For anchored or unanchored matches, there may be a "last known required  /* For anchored or unanchored matches, there may be a "last known required
2795  character" set. */  character" set. */
2796    
2797  if ((re->options & PCRE_REQCHSET) != 0)  if ((re->flags & PCRE_REQCHSET) != 0)
2798    {    {
2799    req_byte = re->req_byte & 255;    req_byte = re->req_byte & 255;
2800    req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;    req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;
# Line 1925  if ((re->options & PCRE_REQCHSET) != 0) Line 2802  if ((re->options & 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 1937  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        while (t <= save_end_subject - md->nllen && !IS_NEWLINE(t)) t++;  #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++;
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 + md->nllen +  
           start_offset)  
2850          {          {
2851          while (current_subject <= end_subject &&          if (first_byte_caseless)
2852                 !IS_NEWLINE(current_subject - md->nllen))            while (current_subject < end_subject &&
2853            current_subject++;                   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 a non-unique first char after study */        /* Or to just after a linebreak for a multiline match if possible */
2862    
2863      else if (start_bits != NULL)        else if (startline)
2864        {          {
2865        while (current_subject < end_subject)          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 (current_subject[-1] == CHAR_CR &&
2889                   (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
2890                   current_subject < end_subject &&
2891                   *current_subject == CHAR_NL)
2892                current_subject++;
2893              }
2894            }
2895    
2896          /* Or to a non-unique first char after study */
2897    
2898          else if (start_bits != NULL)
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 2004  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 2049  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 2070  for (;;) Line 2995  for (;;)
2995    /* Advance to the next subject character unless we are at the end of a line    /* Advance to the next subject character unless we are at the end of a line
2996    and firstline is set. */    and firstline is set. */
2997    
2998    if (firstline &&    if (firstline && IS_NEWLINE(current_subject)) break;
       current_subject <= end_subject - md->nllen &&  
       IS_NEWLINE(current_subject)) break;  
2999    current_subject++;    current_subject++;
3000    if (utf8)    if (utf8)
3001      {      {
# Line 2080  for (;;) Line 3003  for (;;)
3003        current_subject++;        current_subject++;
3004      }      }
3005    if (current_subject > end_subject) break;    if (current_subject > end_subject) break;
3006    }  
3007      /* If we have just passed a CR and we are now at a LF, and the pattern does
3008      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. */
3010    
3011      if (current_subject[-1] == CHAR_CR &&
3012          current_subject < end_subject &&
3013          *current_subject == CHAR_NL &&
3014          (re->flags & PCRE_HASCRORLF) == 0 &&
3015            (md->nltype == NLTYPE_ANY ||
3016             md->nltype == NLTYPE_ANYCRLF ||
3017             md->nllen == 2))
3018        current_subject++;
3019    
3020      }   /* "Bumpalong" loop */
3021    
3022  return PCRE_ERROR_NOMATCH;  return PCRE_ERROR_NOMATCH;
3023  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.5