Annotation of win32/pcre/pcre_dfa_exec.c, revision 1.4

1.1       misha       1: /*************************************************
                      2: *      Perl-Compatible Regular Expressions       *
                      3: *************************************************/
                      4: 
                      5: /* PCRE is a library of functions to support regular expressions whose syntax
1.3       misha       6: and semantics are as close as possible to those of the Perl 5 language (but see
                      7: below for why this module is different).
1.1       misha       8: 
                      9:                        Written by Philip Hazel
1.4     ! misha      10:            Copyright (c) 1997-2010 University of Cambridge
1.1       misha      11: 
                     12: -----------------------------------------------------------------------------
                     13: Redistribution and use in source and binary forms, with or without
                     14: modification, are permitted provided that the following conditions are met:
                     15: 
                     16:     * Redistributions of source code must retain the above copyright notice,
                     17:       this list of conditions and the following disclaimer.
                     18: 
                     19:     * Redistributions in binary form must reproduce the above copyright
                     20:       notice, this list of conditions and the following disclaimer in the
                     21:       documentation and/or other materials provided with the distribution.
                     22: 
                     23:     * Neither the name of the University of Cambridge nor the names of its
                     24:       contributors may be used to endorse or promote products derived from
                     25:       this software without specific prior written permission.
                     26: 
                     27: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
                     28: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     29: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     30: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
                     31: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37: POSSIBILITY OF SUCH DAMAGE.
                     38: -----------------------------------------------------------------------------
                     39: */
                     40: 
                     41: 
                     42: /* This module contains the external function pcre_dfa_exec(), which is an
                     43: alternative matching function that uses a sort of DFA algorithm (not a true
                     44: FSM). This is NOT Perl- compatible, but it has advantages in certain
                     45: applications. */
                     46: 
                     47: 
1.4     ! misha      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: 
1.1       misha      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: 
                     84: #include "pcre_internal.h"
                     85: 
                     86: 
                     87: /* For use to indent debugging output */
                     88: 
                     89: #define SP "                   "
                     90: 
                     91: 
                     92: /*************************************************
                     93: *      Code parameters and static tables         *
                     94: *************************************************/
                     95: 
                     96: /* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes
                     97: into others, under special conditions. A gap of 20 between the blocks should be
                     98: 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: 
                    101: #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
1.4     ! misha     109: character that is to be tested in some way. This makes it possible to
1.1       misha     110: 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
1.4     ! misha     112: small value. Non-zero values in the table are the offsets from the opcode where
        !           113: the character is to be found. ***NOTE*** If the start of this table is
        !           114: modified, the three tables that follow must also be modified. */
1.1       misha     115: 
                    116: static const uschar coptable[] = {
                    117:   0,                             /* End                                    */
                    118:   0, 0, 0, 0, 0,                 /* \A, \G, \K, \B, \b                     */
                    119:   0, 0, 0, 0, 0, 0,              /* \D, \d, \S, \s, \W, \w                 */
                    120:   0, 0, 0,                       /* Any, AllAny, Anybyte                   */
1.4     ! misha     121:   0, 0,                          /* \P, \p                                 */
1.1       misha     122:   0, 0, 0, 0, 0,                 /* \R, \H, \h, \V, \v                     */
1.4     ! misha     123:   0,                             /* \X                                     */
1.1       misha     124:   0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, $                      */
                    125:   1,                             /* Char                                   */
                    126:   1,                             /* Charnc                                 */
                    127:   1,                             /* not                                    */
                    128:   /* Positive single-char repeats                                          */
                    129:   1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
                    130:   3, 3, 3,                       /* upto, minupto, exact                   */
                    131:   1, 1, 1, 3,                    /* *+, ++, ?+, upto+                      */
                    132:   /* Negative single-char repeats - only for chars < 256                   */
                    133:   1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
                    134:   3, 3, 3,                       /* NOT upto, minupto, exact               */
                    135:   1, 1, 1, 3,                    /* NOT *+, ++, ?+, updo+                  */
                    136:   /* Positive type repeats                                                 */
                    137:   1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
                    138:   3, 3, 3,                       /* Type upto, minupto, exact              */
                    139:   1, 1, 1, 3,                    /* Type *+, ++, ?+, upto+                 */
                    140:   /* Character class & ref repeats                                         */
                    141:   0, 0, 0, 0, 0, 0,              /* *, *?, +, +?, ?, ??                    */
                    142:   0, 0,                          /* CRRANGE, CRMINRANGE                    */
                    143:   0,                             /* CLASS                                  */
                    144:   0,                             /* NCLASS                                 */
                    145:   0,                             /* XCLASS - variable length               */
                    146:   0,                             /* REF                                    */
                    147:   0,                             /* RECURSE                                */
                    148:   0,                             /* CALLOUT                                */
                    149:   0,                             /* Alt                                    */
                    150:   0,                             /* Ket                                    */
                    151:   0,                             /* KetRmax                                */
                    152:   0,                             /* KetRmin                                */
                    153:   0,                             /* Assert                                 */
                    154:   0,                             /* Assert not                             */
                    155:   0,                             /* Assert behind                          */
                    156:   0,                             /* Assert behind not                      */
                    157:   0,                             /* Reverse                                */
                    158:   0, 0, 0, 0,                    /* ONCE, BRA, CBRA, COND                  */
                    159:   0, 0, 0,                       /* SBRA, SCBRA, SCOND                     */
1.4     ! misha     160:   0, 0,                          /* CREF, NCREF                            */
        !           161:   0, 0,                          /* RREF, NRREF                            */
1.1       misha     162:   0,                             /* DEF                                    */
                    163:   0, 0,                          /* BRAZERO, BRAMINZERO                    */
1.4     ! misha     164:   0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG,                */
        !           165:   0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG,        */
        !           166:   0, 0, 0, 0, 0                  /* COMMIT, FAIL, ACCEPT, CLOSE, SKIPZERO  */
        !           167: };
        !           168: 
        !           169: /* This table identifies those opcodes that inspect a character. It is used to
        !           170: remember the fact that a character could have been inspected when the end of
        !           171: the subject is reached. ***NOTE*** If the start of this table is modified, the
        !           172: two tables that follow must also be modified. */
        !           173: 
        !           174: static const uschar poptable[] = {
        !           175:   0,                             /* End                                    */
        !           176:   0, 0, 0, 1, 1,                 /* \A, \G, \K, \B, \b                     */
        !           177:   1, 1, 1, 1, 1, 1,              /* \D, \d, \S, \s, \W, \w                 */
        !           178:   1, 1, 1,                       /* Any, AllAny, Anybyte                   */
        !           179:   1, 1,                          /* \P, \p                                 */
        !           180:   1, 1, 1, 1, 1,                 /* \R, \H, \h, \V, \v                     */
        !           181:   1,                             /* \X                                     */
        !           182:   0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, $                      */
        !           183:   1,                             /* Char                                   */
        !           184:   1,                             /* Charnc                                 */
        !           185:   1,                             /* not                                    */
        !           186:   /* Positive single-char repeats                                          */
        !           187:   1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
        !           188:   1, 1, 1,                       /* upto, minupto, exact                   */
        !           189:   1, 1, 1, 1,                    /* *+, ++, ?+, upto+                      */
        !           190:   /* Negative single-char repeats - only for chars < 256                   */
        !           191:   1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
        !           192:   1, 1, 1,                       /* NOT upto, minupto, exact               */
        !           193:   1, 1, 1, 1,                    /* NOT *+, ++, ?+, upto+                  */
        !           194:   /* Positive type repeats                                                 */
        !           195:   1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
        !           196:   1, 1, 1,                       /* Type upto, minupto, exact              */
        !           197:   1, 1, 1, 1,                    /* Type *+, ++, ?+, upto+                 */
        !           198:   /* Character class & ref repeats                                         */
        !           199:   1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
        !           200:   1, 1,                          /* CRRANGE, CRMINRANGE                    */
        !           201:   1,                             /* CLASS                                  */
        !           202:   1,                             /* NCLASS                                 */
        !           203:   1,                             /* XCLASS - variable length               */
        !           204:   0,                             /* REF                                    */
        !           205:   0,                             /* RECURSE                                */
        !           206:   0,                             /* CALLOUT                                */
        !           207:   0,                             /* Alt                                    */
        !           208:   0,                             /* Ket                                    */
        !           209:   0,                             /* KetRmax                                */
        !           210:   0,                             /* KetRmin                                */
        !           211:   0,                             /* Assert                                 */
        !           212:   0,                             /* Assert not                             */
        !           213:   0,                             /* Assert behind                          */
        !           214:   0,                             /* Assert behind not                      */
        !           215:   0,                             /* Reverse                                */
        !           216:   0, 0, 0, 0,                    /* ONCE, BRA, CBRA, COND                  */
        !           217:   0, 0, 0,                       /* SBRA, SCBRA, SCOND                     */
        !           218:   0, 0,                          /* CREF, NCREF                            */
        !           219:   0, 0,                          /* RREF, NRREF                            */
        !           220:   0,                             /* DEF                                    */
        !           221:   0, 0,                          /* BRAZERO, BRAMINZERO                    */
        !           222:   0, 0, 0,                       /* MARK, PRUNE, PRUNE_ARG,                */
        !           223:   0, 0, 0, 0,                    /* SKIP, SKIP_ARG, THEN, THEN_ARG,        */
        !           224:   0, 0, 0, 0, 0                  /* COMMIT, FAIL, ACCEPT, CLOSE, SKIPZERO  */
1.1       misha     225: };
                    226: 
                    227: /* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,
                    228: and \w */
                    229: 
                    230: static const uschar toptable1[] = {
                    231:   0, 0, 0, 0, 0, 0,
                    232:   ctype_digit, ctype_digit,
                    233:   ctype_space, ctype_space,
                    234:   ctype_word,  ctype_word,
                    235:   0, 0                            /* OP_ANY, OP_ALLANY */
                    236: };
                    237: 
                    238: static const uschar toptable2[] = {
                    239:   0, 0, 0, 0, 0, 0,
                    240:   ctype_digit, 0,
                    241:   ctype_space, 0,
                    242:   ctype_word,  0,
                    243:   1, 1                            /* OP_ANY, OP_ALLANY */
                    244: };
                    245: 
                    246: 
                    247: /* Structure for holding data about a particular state, which is in effect the
                    248: current data for an active path through the match tree. It must consist
                    249: entirely of ints because the working vector we are passed, and which we put
                    250: these structures in, is a vector of ints. */
                    251: 
                    252: typedef struct stateblock {
                    253:   int offset;                     /* Offset to opcode */
                    254:   int count;                      /* Count for repeats */
                    255:   int ims;                        /* ims flag bits */
                    256:   int data;                       /* Some use extra data */
                    257: } stateblock;
                    258: 
                    259: #define INTS_PER_STATEBLOCK  (sizeof(stateblock)/sizeof(int))
                    260: 
                    261: 
1.4     ! misha     262: #ifdef PCRE_DEBUG
1.1       misha     263: /*************************************************
                    264: *             Print character string             *
                    265: *************************************************/
                    266: 
                    267: /* Character string printing function for debugging.
                    268: 
                    269: Arguments:
                    270:   p            points to string
                    271:   length       number of bytes
                    272:   f            where to print
                    273: 
                    274: Returns:       nothing
                    275: */
                    276: 
                    277: static void
                    278: pchars(unsigned char *p, int length, FILE *f)
                    279: {
                    280: int c;
                    281: while (length-- > 0)
                    282:   {
                    283:   if (isprint(c = *(p++)))
                    284:     fprintf(f, "%c", c);
                    285:   else
                    286:     fprintf(f, "\\x%02x", c);
                    287:   }
                    288: }
                    289: #endif
                    290: 
                    291: 
                    292: 
                    293: /*************************************************
                    294: *    Execute a Regular Expression - DFA engine   *
                    295: *************************************************/
                    296: 
                    297: /* This internal function applies a compiled pattern to a subject string,
                    298: starting at a given point, using a DFA engine. This function is called from the
                    299: external one, possibly multiple times if the pattern is not anchored. The
                    300: function calls itself recursively for some kinds of subpattern.
                    301: 
                    302: Arguments:
                    303:   md                the match_data block with fixed information
                    304:   this_start_code   the opening bracket of this subexpression's code
                    305:   current_subject   where we currently are in the subject string
                    306:   start_offset      start offset in the subject string
                    307:   offsets           vector to contain the matching string offsets
                    308:   offsetcount       size of same
                    309:   workspace         vector of workspace
                    310:   wscount           size of same
                    311:   ims               the current ims flags
                    312:   rlevel            function call recursion level
                    313:   recursing         regex recursive call level
                    314: 
                    315: Returns:            > 0 => number of match offset pairs placed in offsets
                    316:                     = 0 => offsets overflowed; longest matches are present
                    317:                      -1 => failed to match
                    318:                    < -1 => some kind of unexpected problem
                    319: 
                    320: The following macros are used for adding states to the two state vectors (one
                    321: for the current character, one for the following character). */
                    322: 
                    323: #define ADD_ACTIVE(x,y) \
                    324:   if (active_count++ < wscount) \
                    325:     { \
                    326:     next_active_state->offset = (x); \
                    327:     next_active_state->count  = (y); \
                    328:     next_active_state->ims    = ims; \
                    329:     next_active_state++; \
                    330:     DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
                    331:     } \
                    332:   else return PCRE_ERROR_DFA_WSSIZE
                    333: 
                    334: #define ADD_ACTIVE_DATA(x,y,z) \
                    335:   if (active_count++ < wscount) \
                    336:     { \
                    337:     next_active_state->offset = (x); \
                    338:     next_active_state->count  = (y); \
                    339:     next_active_state->ims    = ims; \
                    340:     next_active_state->data   = (z); \
                    341:     next_active_state++; \
                    342:     DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \
                    343:     } \
                    344:   else return PCRE_ERROR_DFA_WSSIZE
                    345: 
                    346: #define ADD_NEW(x,y) \
                    347:   if (new_count++ < wscount) \
                    348:     { \
                    349:     next_new_state->offset = (x); \
                    350:     next_new_state->count  = (y); \
                    351:     next_new_state->ims    = ims; \
                    352:     next_new_state++; \
                    353:     DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
                    354:     } \
                    355:   else return PCRE_ERROR_DFA_WSSIZE
                    356: 
                    357: #define ADD_NEW_DATA(x,y,z) \
                    358:   if (new_count++ < wscount) \
                    359:     { \
                    360:     next_new_state->offset = (x); \
                    361:     next_new_state->count  = (y); \
                    362:     next_new_state->ims    = ims; \
                    363:     next_new_state->data   = (z); \
                    364:     next_new_state++; \
                    365:     DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \
                    366:     } \
                    367:   else return PCRE_ERROR_DFA_WSSIZE
                    368: 
                    369: /* And now, here is the code */
                    370: 
                    371: static int
                    372: internal_dfa_exec(
                    373:   dfa_match_data *md,
                    374:   const uschar *this_start_code,
                    375:   const uschar *current_subject,
                    376:   int start_offset,
                    377:   int *offsets,
                    378:   int offsetcount,
                    379:   int *workspace,
                    380:   int wscount,
                    381:   int ims,
                    382:   int  rlevel,
                    383:   int  recursing)
                    384: {
                    385: stateblock *active_states, *new_states, *temp_states;
                    386: stateblock *next_active_state, *next_new_state;
                    387: 
                    388: const uschar *ctypes, *lcc, *fcc;
                    389: const uschar *ptr;
                    390: const uschar *end_code, *first_op;
                    391: 
                    392: int active_count, new_count, match_count;
                    393: 
                    394: /* Some fields in the md block are frequently referenced, so we load them into
                    395: independent variables in the hope that this will perform better. */
                    396: 
                    397: const uschar *start_subject = md->start_subject;
                    398: const uschar *end_subject = md->end_subject;
                    399: const uschar *start_code = md->start_code;
                    400: 
                    401: #ifdef SUPPORT_UTF8
                    402: BOOL utf8 = (md->poptions & PCRE_UTF8) != 0;
                    403: #else
                    404: BOOL utf8 = FALSE;
                    405: #endif
                    406: 
                    407: rlevel++;
                    408: offsetcount &= (-2);
                    409: 
                    410: wscount -= 2;
                    411: wscount = (wscount - (wscount % (INTS_PER_STATEBLOCK * 2))) /
                    412:           (2 * INTS_PER_STATEBLOCK);
                    413: 
                    414: DPRINTF(("\n%.*s---------------------\n"
                    415:   "%.*sCall to internal_dfa_exec f=%d r=%d\n",
                    416:   rlevel*2-2, SP, rlevel*2-2, SP, rlevel, recursing));
                    417: 
                    418: ctypes = md->tables + ctypes_offset;
                    419: lcc = md->tables + lcc_offset;
                    420: fcc = md->tables + fcc_offset;
                    421: 
                    422: match_count = PCRE_ERROR_NOMATCH;   /* A negative number */
                    423: 
                    424: active_states = (stateblock *)(workspace + 2);
                    425: next_new_state = new_states = active_states + wscount;
                    426: new_count = 0;
                    427: 
                    428: first_op = this_start_code + 1 + LINK_SIZE +
                    429:   ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA)? 2:0);
                    430: 
                    431: /* The first thing in any (sub) pattern is a bracket of some sort. Push all
                    432: the alternative states onto the list, and find out where the end is. This
                    433: makes is possible to use this function recursively, when we want to stop at a
                    434: matching internal ket rather than at the end.
                    435: 
                    436: If the first opcode in the first alternative is OP_REVERSE, we are dealing with
                    437: a backward assertion. In that case, we have to find out the maximum amount to
                    438: move back, and set up each alternative appropriately. */
                    439: 
                    440: if (*first_op == OP_REVERSE)
                    441:   {
                    442:   int max_back = 0;
                    443:   int gone_back;
                    444: 
                    445:   end_code = this_start_code;
                    446:   do
                    447:     {
                    448:     int back = GET(end_code, 2+LINK_SIZE);
                    449:     if (back > max_back) max_back = back;
                    450:     end_code += GET(end_code, 1);
                    451:     }
                    452:   while (*end_code == OP_ALT);
                    453: 
                    454:   /* If we can't go back the amount required for the longest lookbehind
                    455:   pattern, go back as far as we can; some alternatives may still be viable. */
                    456: 
                    457: #ifdef SUPPORT_UTF8
                    458:   /* In character mode we have to step back character by character */
                    459: 
                    460:   if (utf8)
                    461:     {
                    462:     for (gone_back = 0; gone_back < max_back; gone_back++)
                    463:       {
                    464:       if (current_subject <= start_subject) break;
                    465:       current_subject--;
                    466:       while (current_subject > start_subject &&
                    467:              (*current_subject & 0xc0) == 0x80)
                    468:         current_subject--;
                    469:       }
                    470:     }
                    471:   else
                    472: #endif
                    473: 
                    474:   /* In byte-mode we can do this quickly. */
                    475: 
                    476:     {
                    477:     gone_back = (current_subject - max_back < start_subject)?
1.4     ! misha     478:       (int)(current_subject - start_subject) : max_back;
1.1       misha     479:     current_subject -= gone_back;
                    480:     }
                    481: 
1.4     ! misha     482:   /* Save the earliest consulted character */
        !           483: 
        !           484:   if (current_subject < md->start_used_ptr)
        !           485:     md->start_used_ptr = current_subject;
        !           486: 
1.1       misha     487:   /* Now we can process the individual branches. */
                    488: 
                    489:   end_code = this_start_code;
                    490:   do
                    491:     {
                    492:     int back = GET(end_code, 2+LINK_SIZE);
                    493:     if (back <= gone_back)
                    494:       {
1.4     ! misha     495:       int bstate = (int)(end_code - start_code + 2 + 2*LINK_SIZE);
1.1       misha     496:       ADD_NEW_DATA(-bstate, 0, gone_back - back);
                    497:       }
                    498:     end_code += GET(end_code, 1);
                    499:     }
                    500:   while (*end_code == OP_ALT);
                    501:  }
                    502: 
                    503: /* This is the code for a "normal" subpattern (not a backward assertion). The
                    504: start of a whole pattern is always one of these. If we are at the top level,
                    505: we may be asked to restart matching from the same point that we reached for a
                    506: previous partial match. We still have to scan through the top-level branches to
                    507: find the end state. */
                    508: 
                    509: else
                    510:   {
                    511:   end_code = this_start_code;
                    512: 
                    513:   /* Restarting */
                    514: 
                    515:   if (rlevel == 1 && (md->moptions & PCRE_DFA_RESTART) != 0)
                    516:     {
                    517:     do { end_code += GET(end_code, 1); } while (*end_code == OP_ALT);
                    518:     new_count = workspace[1];
                    519:     if (!workspace[0])
                    520:       memcpy(new_states, active_states, new_count * sizeof(stateblock));
                    521:     }
                    522: 
                    523:   /* Not restarting */
                    524: 
                    525:   else
                    526:     {
                    527:     int length = 1 + LINK_SIZE +
                    528:       ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA)? 2:0);
                    529:     do
                    530:       {
1.4     ! misha     531:       ADD_NEW((int)(end_code - start_code + length), 0);
1.1       misha     532:       end_code += GET(end_code, 1);
                    533:       length = 1 + LINK_SIZE;
                    534:       }
                    535:     while (*end_code == OP_ALT);
                    536:     }
                    537:   }
                    538: 
                    539: workspace[0] = 0;    /* Bit indicating which vector is current */
                    540: 
                    541: DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, end_code - start_code));
                    542: 
                    543: /* Loop for scanning the subject */
                    544: 
                    545: ptr = current_subject;
                    546: for (;;)
                    547:   {
                    548:   int i, j;
                    549:   int clen, dlen;
                    550:   unsigned int c, d;
1.4     ! misha     551:   int forced_fail = 0;
        !           552:   BOOL could_continue = FALSE;
1.1       misha     553: 
                    554:   /* Make the new state list into the active state list and empty the
                    555:   new state list. */
                    556: 
                    557:   temp_states = active_states;
                    558:   active_states = new_states;
                    559:   new_states = temp_states;
                    560:   active_count = new_count;
                    561:   new_count = 0;
                    562: 
                    563:   workspace[0] ^= 1;              /* Remember for the restarting feature */
                    564:   workspace[1] = active_count;
                    565: 
1.4     ! misha     566: #ifdef PCRE_DEBUG
1.1       misha     567:   printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP);
                    568:   pchars((uschar *)ptr, strlen((char *)ptr), stdout);
                    569:   printf("\"\n");
                    570: 
                    571:   printf("%.*sActive states: ", rlevel*2-2, SP);
                    572:   for (i = 0; i < active_count; i++)
                    573:     printf("%d/%d ", active_states[i].offset, active_states[i].count);
                    574:   printf("\n");
                    575: #endif
                    576: 
                    577:   /* Set the pointers for adding new states */
                    578: 
                    579:   next_active_state = active_states + active_count;
                    580:   next_new_state = new_states;
                    581: 
                    582:   /* Load the current character from the subject outside the loop, as many
                    583:   different states may want to look at it, and we assume that at least one
                    584:   will. */
                    585: 
                    586:   if (ptr < end_subject)
                    587:     {
                    588:     clen = 1;        /* Number of bytes in the character */
                    589: #ifdef SUPPORT_UTF8
                    590:     if (utf8) { GETCHARLEN(c, ptr, clen); } else
                    591: #endif  /* SUPPORT_UTF8 */
                    592:     c = *ptr;
                    593:     }
                    594:   else
                    595:     {
                    596:     clen = 0;        /* This indicates the end of the subject */
                    597:     c = NOTACHAR;    /* This value should never actually be used */
                    598:     }
                    599: 
                    600:   /* Scan up the active states and act on each one. The result of an action
                    601:   may be to add more states to the currently active list (e.g. on hitting a
                    602:   parenthesis) or it may be to put states on the new list, for considering
                    603:   when we move the character pointer on. */
                    604: 
                    605:   for (i = 0; i < active_count; i++)
                    606:     {
                    607:     stateblock *current_state = active_states + i;
                    608:     const uschar *code;
                    609:     int state_offset = current_state->offset;
1.3       misha     610:     int count, codevalue, rrc;
1.1       misha     611: 
1.4     ! misha     612: #ifdef PCRE_DEBUG
1.1       misha     613:     printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset);
                    614:     if (clen == 0) printf("EOL\n");
                    615:       else if (c > 32 && c < 127) printf("'%c'\n", c);
                    616:         else printf("0x%02x\n", c);
                    617: #endif
                    618: 
                    619:     /* This variable is referred to implicity in the ADD_xxx macros. */
                    620: 
                    621:     ims = current_state->ims;
                    622: 
                    623:     /* A negative offset is a special case meaning "hold off going to this
                    624:     (negated) state until the number of characters in the data field have
                    625:     been skipped". */
                    626: 
                    627:     if (state_offset < 0)
                    628:       {
                    629:       if (current_state->data > 0)
                    630:         {
                    631:         DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP));
                    632:         ADD_NEW_DATA(state_offset, current_state->count,
                    633:           current_state->data - 1);
                    634:         continue;
                    635:         }
                    636:       else
                    637:         {
                    638:         current_state->offset = state_offset = -state_offset;
                    639:         }
                    640:       }
                    641: 
1.4     ! misha     642:     /* Check for a duplicate state with the same count, and skip if found.
        !           643:     See the note at the head of this module about the possibility of improving
        !           644:     performance here. */
1.1       misha     645: 
                    646:     for (j = 0; j < i; j++)
                    647:       {
                    648:       if (active_states[j].offset == state_offset &&
                    649:           active_states[j].count == current_state->count)
                    650:         {
                    651:         DPRINTF(("%.*sDuplicate state: skipped\n", rlevel*2-2, SP));
                    652:         goto NEXT_ACTIVE_STATE;
                    653:         }
                    654:       }
                    655: 
                    656:     /* The state offset is the offset to the opcode */
                    657: 
                    658:     code = start_code + state_offset;
                    659:     codevalue = *code;
                    660: 
1.4     ! misha     661:     /* If this opcode inspects a character, but we are at the end of the
        !           662:     subject, remember the fact for use when testing for a partial match. */
        !           663: 
        !           664:     if (clen == 0 && poptable[codevalue] != 0)
        !           665:       could_continue = TRUE;
        !           666: 
1.1       misha     667:     /* If this opcode is followed by an inline character, load it. It is
                    668:     tempting to test for the presence of a subject character here, but that
                    669:     is wrong, because sometimes zero repetitions of the subject are
                    670:     permitted.
                    671: 
                    672:     We also use this mechanism for opcodes such as OP_TYPEPLUS that take an
                    673:     argument that is not a data character - but is always one byte long. We
                    674:     have to take special action to deal with  \P, \p, \H, \h, \V, \v and \X in
                    675:     this case. To keep the other cases fast, convert these ones to new opcodes.
                    676:     */
                    677: 
                    678:     if (coptable[codevalue] > 0)
                    679:       {
                    680:       dlen = 1;
                    681: #ifdef SUPPORT_UTF8
                    682:       if (utf8) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else
                    683: #endif  /* SUPPORT_UTF8 */
                    684:       d = code[coptable[codevalue]];
                    685:       if (codevalue >= OP_TYPESTAR)
                    686:         {
                    687:         switch(d)
                    688:           {
                    689:           case OP_ANYBYTE: return PCRE_ERROR_DFA_UITEM;
                    690:           case OP_NOTPROP:
                    691:           case OP_PROP: codevalue += OP_PROP_EXTRA; break;
                    692:           case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break;
                    693:           case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break;
                    694:           case OP_NOT_HSPACE:
                    695:           case OP_HSPACE: codevalue += OP_HSPACE_EXTRA; break;
                    696:           case OP_NOT_VSPACE:
                    697:           case OP_VSPACE: codevalue += OP_VSPACE_EXTRA; break;
                    698:           default: break;
                    699:           }
                    700:         }
                    701:       }
                    702:     else
                    703:       {
                    704:       dlen = 0;         /* Not strictly necessary, but compilers moan */
                    705:       d = NOTACHAR;     /* if these variables are not set. */
                    706:       }
                    707: 
                    708: 
                    709:     /* Now process the individual opcodes */
                    710: 
                    711:     switch (codevalue)
                    712:       {
1.4     ! misha     713: /* ========================================================================== */
        !           714:       /* These cases are never obeyed. This is a fudge that causes a compile-
        !           715:       time error if the vectors coptable or poptable, which are indexed by
        !           716:       opcode, are not the correct length. It seems to be the only way to do
        !           717:       such a check at compile time, as the sizeof() operator does not work
        !           718:       in the C preprocessor. */
        !           719: 
        !           720:       case OP_TABLE_LENGTH:
        !           721:       case OP_TABLE_LENGTH +
        !           722:         ((sizeof(coptable) == OP_TABLE_LENGTH) &&
        !           723:          (sizeof(poptable) == OP_TABLE_LENGTH)):
        !           724:       break;
1.1       misha     725: 
                    726: /* ========================================================================== */
                    727:       /* Reached a closing bracket. If not at the end of the pattern, carry
                    728:       on with the next opcode. Otherwise, unless we have an empty string and
1.4     ! misha     729:       PCRE_NOTEMPTY is set, or PCRE_NOTEMPTY_ATSTART is set and we are at the
        !           730:       start of the subject, save the match data, shifting up all previous
1.1       misha     731:       matches so we always have the longest first. */
                    732: 
                    733:       case OP_KET:
                    734:       case OP_KETRMIN:
                    735:       case OP_KETRMAX:
                    736:       if (code != end_code)
                    737:         {
                    738:         ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0);
                    739:         if (codevalue != OP_KET)
                    740:           {
                    741:           ADD_ACTIVE(state_offset - GET(code, 1), 0);
                    742:           }
                    743:         }
1.4     ! misha     744:       else
1.1       misha     745:         {
1.4     ! misha     746:         if (ptr > current_subject ||
        !           747:             ((md->moptions & PCRE_NOTEMPTY) == 0 &&
        !           748:               ((md->moptions & PCRE_NOTEMPTY_ATSTART) == 0 ||
        !           749:                 current_subject > start_subject + md->start_offset)))
        !           750:           {
        !           751:           if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;
        !           752:             else if (match_count > 0 && ++match_count * 2 >= offsetcount)
        !           753:               match_count = 0;
        !           754:           count = ((match_count == 0)? offsetcount : match_count * 2) - 2;
        !           755:           if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));
        !           756:           if (offsetcount >= 2)
        !           757:             {
        !           758:             offsets[0] = (int)(current_subject - start_subject);
        !           759:             offsets[1] = (int)(ptr - start_subject);
        !           760:             DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,
        !           761:               offsets[1] - offsets[0], current_subject));
        !           762:             }
        !           763:           if ((md->moptions & PCRE_DFA_SHORTEST) != 0)
        !           764:             {
        !           765:             DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"
        !           766:               "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel,
        !           767:               match_count, rlevel*2-2, SP));
        !           768:             return match_count;
        !           769:             }
1.1       misha     770:           }
                    771:         }
                    772:       break;
                    773: 
                    774: /* ========================================================================== */
                    775:       /* These opcodes add to the current list of states without looking
                    776:       at the current character. */
                    777: 
                    778:       /*-----------------------------------------------------------------*/
                    779:       case OP_ALT:
                    780:       do { code += GET(code, 1); } while (*code == OP_ALT);
1.4     ! misha     781:       ADD_ACTIVE((int)(code - start_code), 0);
1.1       misha     782:       break;
                    783: 
                    784:       /*-----------------------------------------------------------------*/
                    785:       case OP_BRA:
                    786:       case OP_SBRA:
                    787:       do
                    788:         {
1.4     ! misha     789:         ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);
1.1       misha     790:         code += GET(code, 1);
                    791:         }
                    792:       while (*code == OP_ALT);
                    793:       break;
                    794: 
                    795:       /*-----------------------------------------------------------------*/
                    796:       case OP_CBRA:
                    797:       case OP_SCBRA:
1.4     ! misha     798:       ADD_ACTIVE((int)(code - start_code + 3 + LINK_SIZE),  0);
1.1       misha     799:       code += GET(code, 1);
                    800:       while (*code == OP_ALT)
                    801:         {
1.4     ! misha     802:         ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE),  0);
1.1       misha     803:         code += GET(code, 1);
                    804:         }
                    805:       break;
                    806: 
                    807:       /*-----------------------------------------------------------------*/
                    808:       case OP_BRAZERO:
                    809:       case OP_BRAMINZERO:
                    810:       ADD_ACTIVE(state_offset + 1, 0);
                    811:       code += 1 + GET(code, 2);
                    812:       while (*code == OP_ALT) code += GET(code, 1);
1.4     ! misha     813:       ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);
1.1       misha     814:       break;
                    815: 
                    816:       /*-----------------------------------------------------------------*/
                    817:       case OP_SKIPZERO:
                    818:       code += 1 + GET(code, 2);
                    819:       while (*code == OP_ALT) code += GET(code, 1);
1.4     ! misha     820:       ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);
1.1       misha     821:       break;
                    822: 
                    823:       /*-----------------------------------------------------------------*/
                    824:       case OP_CIRC:
                    825:       if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||
                    826:           ((ims & PCRE_MULTILINE) != 0 &&
                    827:             ptr != end_subject &&
                    828:             WAS_NEWLINE(ptr)))
                    829:         { ADD_ACTIVE(state_offset + 1, 0); }
                    830:       break;
                    831: 
                    832:       /*-----------------------------------------------------------------*/
                    833:       case OP_EOD:
                    834:       if (ptr >= end_subject) { ADD_ACTIVE(state_offset + 1, 0); }
                    835:       break;
                    836: 
                    837:       /*-----------------------------------------------------------------*/
                    838:       case OP_OPT:
                    839:       ims = code[1];
                    840:       ADD_ACTIVE(state_offset + 2, 0);
                    841:       break;
                    842: 
                    843:       /*-----------------------------------------------------------------*/
                    844:       case OP_SOD:
                    845:       if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); }
                    846:       break;
                    847: 
                    848:       /*-----------------------------------------------------------------*/
                    849:       case OP_SOM:
                    850:       if (ptr == start_subject + start_offset) { ADD_ACTIVE(state_offset + 1, 0); }
                    851:       break;
                    852: 
                    853: 
                    854: /* ========================================================================== */
                    855:       /* These opcodes inspect the next subject character, and sometimes
                    856:       the previous one as well, but do not have an argument. The variable
                    857:       clen contains the length of the current character and is zero if we are
                    858:       at the end of the subject. */
                    859: 
                    860:       /*-----------------------------------------------------------------*/
                    861:       case OP_ANY:
                    862:       if (clen > 0 && !IS_NEWLINE(ptr))
                    863:         { ADD_NEW(state_offset + 1, 0); }
                    864:       break;
                    865: 
                    866:       /*-----------------------------------------------------------------*/
                    867:       case OP_ALLANY:
                    868:       if (clen > 0)
                    869:         { ADD_NEW(state_offset + 1, 0); }
                    870:       break;
                    871: 
                    872:       /*-----------------------------------------------------------------*/
                    873:       case OP_EODN:
                    874:       if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen))
                    875:         { ADD_ACTIVE(state_offset + 1, 0); }
                    876:       break;
                    877: 
                    878:       /*-----------------------------------------------------------------*/
                    879:       case OP_DOLL:
                    880:       if ((md->moptions & PCRE_NOTEOL) == 0)
                    881:         {
                    882:         if (clen == 0 ||
1.3       misha     883:             ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&
1.1       misha     884:                ((ims & PCRE_MULTILINE) != 0 || ptr == end_subject - md->nllen)
                    885:             ))
                    886:           { ADD_ACTIVE(state_offset + 1, 0); }
                    887:         }
                    888:       else if ((ims & PCRE_MULTILINE) != 0 && IS_NEWLINE(ptr))
                    889:         { ADD_ACTIVE(state_offset + 1, 0); }
                    890:       break;
                    891: 
                    892:       /*-----------------------------------------------------------------*/
                    893: 
                    894:       case OP_DIGIT:
                    895:       case OP_WHITESPACE:
                    896:       case OP_WORDCHAR:
                    897:       if (clen > 0 && c < 256 &&
                    898:             ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0)
                    899:         { ADD_NEW(state_offset + 1, 0); }
                    900:       break;
                    901: 
                    902:       /*-----------------------------------------------------------------*/
                    903:       case OP_NOT_DIGIT:
                    904:       case OP_NOT_WHITESPACE:
                    905:       case OP_NOT_WORDCHAR:
                    906:       if (clen > 0 && (c >= 256 ||
                    907:             ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0))
                    908:         { ADD_NEW(state_offset + 1, 0); }
                    909:       break;
                    910: 
                    911:       /*-----------------------------------------------------------------*/
                    912:       case OP_WORD_BOUNDARY:
                    913:       case OP_NOT_WORD_BOUNDARY:
                    914:         {
                    915:         int left_word, right_word;
                    916: 
                    917:         if (ptr > start_subject)
                    918:           {
                    919:           const uschar *temp = ptr - 1;
1.4     ! misha     920:           if (temp < md->start_used_ptr) md->start_used_ptr = temp;
1.1       misha     921: #ifdef SUPPORT_UTF8
                    922:           if (utf8) BACKCHAR(temp);
                    923: #endif
                    924:           GETCHARTEST(d, temp);
1.4     ! misha     925: #ifdef SUPPORT_UCP
        !           926:           if ((md->poptions & PCRE_UCP) != 0)
        !           927:             {
        !           928:             if (d == '_') left_word = TRUE; else
        !           929:               {
        !           930:               int cat = UCD_CATEGORY(d);
        !           931:               left_word = (cat == ucp_L || cat == ucp_N);
        !           932:               }
        !           933:             }
        !           934:           else
        !           935: #endif
1.1       misha     936:           left_word = d < 256 && (ctypes[d] & ctype_word) != 0;
                    937:           }
1.4     ! misha     938:         else left_word = FALSE;
1.1       misha     939: 
1.4     ! misha     940:         if (clen > 0)
        !           941:           {
        !           942: #ifdef SUPPORT_UCP
        !           943:           if ((md->poptions & PCRE_UCP) != 0)
        !           944:             {
        !           945:             if (c == '_') right_word = TRUE; else
        !           946:               {
        !           947:               int cat = UCD_CATEGORY(c);
        !           948:               right_word = (cat == ucp_L || cat == ucp_N);
        !           949:               }
        !           950:             }
        !           951:           else
        !           952: #endif
        !           953:           right_word = c < 256 && (ctypes[c] & ctype_word) != 0;
        !           954:           }
        !           955:         else right_word = FALSE;
1.1       misha     956: 
                    957:         if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))
                    958:           { ADD_ACTIVE(state_offset + 1, 0); }
                    959:         }
                    960:       break;
                    961: 
                    962: 
                    963:       /*-----------------------------------------------------------------*/
                    964:       /* Check the next character by Unicode property. We will get here only
                    965:       if the support is in the binary; otherwise a compile-time error occurs.
                    966:       */
                    967: 
                    968: #ifdef SUPPORT_UCP
                    969:       case OP_PROP:
                    970:       case OP_NOTPROP:
                    971:       if (clen > 0)
                    972:         {
                    973:         BOOL OK;
1.2       misha     974:         const ucd_record * prop = GET_UCD(c);
1.1       misha     975:         switch(code[1])
                    976:           {
                    977:           case PT_ANY:
                    978:           OK = TRUE;
                    979:           break;
                    980: 
                    981:           case PT_LAMP:
1.4     ! misha     982:           OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
        !           983:                prop->chartype == ucp_Lt;
1.1       misha     984:           break;
                    985: 
                    986:           case PT_GC:
1.2       misha     987:           OK = _pcre_ucp_gentype[prop->chartype] == code[2];
1.1       misha     988:           break;
                    989: 
                    990:           case PT_PC:
1.2       misha     991:           OK = prop->chartype == code[2];
1.1       misha     992:           break;
                    993: 
                    994:           case PT_SC:
1.2       misha     995:           OK = prop->script == code[2];
1.1       misha     996:           break;
                    997: 
1.4     ! misha     998:           /* These are specials for combination cases. */
        !           999: 
        !          1000:           case PT_ALNUM:
        !          1001:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
        !          1002:                _pcre_ucp_gentype[prop->chartype] == ucp_N;
        !          1003:           break;
        !          1004: 
        !          1005:           case PT_SPACE:    /* Perl space */
        !          1006:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
        !          1007:                c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
        !          1008:           break;
        !          1009: 
        !          1010:           case PT_PXSPACE:  /* POSIX space */
        !          1011:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
        !          1012:                c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
        !          1013:                c == CHAR_FF || c == CHAR_CR;
        !          1014:           break;
        !          1015: 
        !          1016:           case PT_WORD:
        !          1017:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
        !          1018:                _pcre_ucp_gentype[prop->chartype] == ucp_N ||
        !          1019:                c == CHAR_UNDERSCORE;
        !          1020:           break;
        !          1021: 
1.1       misha    1022:           /* Should never occur, but keep compilers from grumbling. */
                   1023: 
                   1024:           default:
                   1025:           OK = codevalue != OP_PROP;
                   1026:           break;
                   1027:           }
                   1028: 
                   1029:         if (OK == (codevalue == OP_PROP)) { ADD_NEW(state_offset + 3, 0); }
                   1030:         }
                   1031:       break;
                   1032: #endif
                   1033: 
                   1034: 
                   1035: 
                   1036: /* ========================================================================== */
                   1037:       /* These opcodes likewise inspect the subject character, but have an
                   1038:       argument that is not a data character. It is one of these opcodes:
                   1039:       OP_ANY, OP_ALLANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE,
                   1040:       OP_WORDCHAR, OP_NOT_WORDCHAR. The value is loaded into d. */
                   1041: 
                   1042:       case OP_TYPEPLUS:
                   1043:       case OP_TYPEMINPLUS:
                   1044:       case OP_TYPEPOSPLUS:
                   1045:       count = current_state->count;  /* Already matched */
                   1046:       if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
                   1047:       if (clen > 0)
                   1048:         {
                   1049:         if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
                   1050:             (c < 256 &&
                   1051:               (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                   1052:               ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
                   1053:           {
                   1054:           if (count > 0 && codevalue == OP_TYPEPOSPLUS)
                   1055:             {
                   1056:             active_count--;            /* Remove non-match possibility */
                   1057:             next_active_state--;
                   1058:             }
                   1059:           count++;
                   1060:           ADD_NEW(state_offset, count);
                   1061:           }
                   1062:         }
                   1063:       break;
                   1064: 
                   1065:       /*-----------------------------------------------------------------*/
                   1066:       case OP_TYPEQUERY:
                   1067:       case OP_TYPEMINQUERY:
                   1068:       case OP_TYPEPOSQUERY:
                   1069:       ADD_ACTIVE(state_offset + 2, 0);
                   1070:       if (clen > 0)
                   1071:         {
                   1072:         if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
                   1073:             (c < 256 &&
                   1074:               (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                   1075:               ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
                   1076:           {
                   1077:           if (codevalue == OP_TYPEPOSQUERY)
                   1078:             {
                   1079:             active_count--;            /* Remove non-match possibility */
                   1080:             next_active_state--;
                   1081:             }
                   1082:           ADD_NEW(state_offset + 2, 0);
                   1083:           }
                   1084:         }
                   1085:       break;
                   1086: 
                   1087:       /*-----------------------------------------------------------------*/
                   1088:       case OP_TYPESTAR:
                   1089:       case OP_TYPEMINSTAR:
                   1090:       case OP_TYPEPOSSTAR:
                   1091:       ADD_ACTIVE(state_offset + 2, 0);
                   1092:       if (clen > 0)
                   1093:         {
                   1094:         if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
                   1095:             (c < 256 &&
                   1096:               (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                   1097:               ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
                   1098:           {
                   1099:           if (codevalue == OP_TYPEPOSSTAR)
                   1100:             {
                   1101:             active_count--;            /* Remove non-match possibility */
                   1102:             next_active_state--;
                   1103:             }
                   1104:           ADD_NEW(state_offset, 0);
                   1105:           }
                   1106:         }
                   1107:       break;
                   1108: 
                   1109:       /*-----------------------------------------------------------------*/
                   1110:       case OP_TYPEEXACT:
                   1111:       count = current_state->count;  /* Number already matched */
                   1112:       if (clen > 0)
                   1113:         {
                   1114:         if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
                   1115:             (c < 256 &&
                   1116:               (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                   1117:               ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
                   1118:           {
                   1119:           if (++count >= GET2(code, 1))
                   1120:             { ADD_NEW(state_offset + 4, 0); }
                   1121:           else
                   1122:             { ADD_NEW(state_offset, count); }
                   1123:           }
                   1124:         }
                   1125:       break;
                   1126: 
                   1127:       /*-----------------------------------------------------------------*/
                   1128:       case OP_TYPEUPTO:
                   1129:       case OP_TYPEMINUPTO:
                   1130:       case OP_TYPEPOSUPTO:
                   1131:       ADD_ACTIVE(state_offset + 4, 0);
                   1132:       count = current_state->count;  /* Number already matched */
                   1133:       if (clen > 0)
                   1134:         {
                   1135:         if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
                   1136:             (c < 256 &&
                   1137:               (d != OP_ANY || !IS_NEWLINE(ptr)) &&
                   1138:               ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
                   1139:           {
                   1140:           if (codevalue == OP_TYPEPOSUPTO)
                   1141:             {
                   1142:             active_count--;           /* Remove non-match possibility */
                   1143:             next_active_state--;
                   1144:             }
                   1145:           if (++count >= GET2(code, 1))
                   1146:             { ADD_NEW(state_offset + 4, 0); }
                   1147:           else
                   1148:             { ADD_NEW(state_offset, count); }
                   1149:           }
                   1150:         }
                   1151:       break;
                   1152: 
                   1153: /* ========================================================================== */
                   1154:       /* These are virtual opcodes that are used when something like
                   1155:       OP_TYPEPLUS has OP_PROP, OP_NOTPROP, OP_ANYNL, or OP_EXTUNI as its
                   1156:       argument. It keeps the code above fast for the other cases. The argument
                   1157:       is in the d variable. */
                   1158: 
                   1159: #ifdef SUPPORT_UCP
                   1160:       case OP_PROP_EXTRA + OP_TYPEPLUS:
                   1161:       case OP_PROP_EXTRA + OP_TYPEMINPLUS:
                   1162:       case OP_PROP_EXTRA + OP_TYPEPOSPLUS:
                   1163:       count = current_state->count;           /* Already matched */
                   1164:       if (count > 0) { ADD_ACTIVE(state_offset + 4, 0); }
                   1165:       if (clen > 0)
                   1166:         {
                   1167:         BOOL OK;
1.2       misha    1168:         const ucd_record * prop = GET_UCD(c);
1.1       misha    1169:         switch(code[2])
                   1170:           {
                   1171:           case PT_ANY:
                   1172:           OK = TRUE;
                   1173:           break;
                   1174: 
                   1175:           case PT_LAMP:
1.4     ! misha    1176:           OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
        !          1177:             prop->chartype == ucp_Lt;
1.1       misha    1178:           break;
                   1179: 
                   1180:           case PT_GC:
1.2       misha    1181:           OK = _pcre_ucp_gentype[prop->chartype] == code[3];
1.1       misha    1182:           break;
                   1183: 
                   1184:           case PT_PC:
1.2       misha    1185:           OK = prop->chartype == code[3];
1.1       misha    1186:           break;
                   1187: 
                   1188:           case PT_SC:
1.2       misha    1189:           OK = prop->script == code[3];
1.1       misha    1190:           break;
                   1191: 
1.4     ! misha    1192:           /* These are specials for combination cases. */
        !          1193: 
        !          1194:           case PT_ALNUM:
        !          1195:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
        !          1196:                _pcre_ucp_gentype[prop->chartype] == ucp_N;
        !          1197:           break;
        !          1198: 
        !          1199:           case PT_SPACE:    /* Perl space */
        !          1200:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
        !          1201:                c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
        !          1202:           break;
        !          1203: 
        !          1204:           case PT_PXSPACE:  /* POSIX space */
        !          1205:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
        !          1206:                c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
        !          1207:                c == CHAR_FF || c == CHAR_CR;
        !          1208:           break;
        !          1209: 
        !          1210:           case PT_WORD:
        !          1211:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
        !          1212:                _pcre_ucp_gentype[prop->chartype] == ucp_N ||
        !          1213:                c == CHAR_UNDERSCORE;
        !          1214:           break;
        !          1215: 
1.1       misha    1216:           /* Should never occur, but keep compilers from grumbling. */
                   1217: 
                   1218:           default:
                   1219:           OK = codevalue != OP_PROP;
                   1220:           break;
                   1221:           }
                   1222: 
                   1223:         if (OK == (d == OP_PROP))
                   1224:           {
                   1225:           if (count > 0 && codevalue == OP_PROP_EXTRA + OP_TYPEPOSPLUS)
                   1226:             {
                   1227:             active_count--;           /* Remove non-match possibility */
                   1228:             next_active_state--;
                   1229:             }
                   1230:           count++;
                   1231:           ADD_NEW(state_offset, count);
                   1232:           }
                   1233:         }
                   1234:       break;
                   1235: 
                   1236:       /*-----------------------------------------------------------------*/
                   1237:       case OP_EXTUNI_EXTRA + OP_TYPEPLUS:
                   1238:       case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS:
                   1239:       case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:
                   1240:       count = current_state->count;  /* Already matched */
                   1241:       if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
1.2       misha    1242:       if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1.1       misha    1243:         {
                   1244:         const uschar *nptr = ptr + clen;
                   1245:         int ncount = 0;
                   1246:         if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)
                   1247:           {
                   1248:           active_count--;           /* Remove non-match possibility */
                   1249:           next_active_state--;
                   1250:           }
                   1251:         while (nptr < end_subject)
                   1252:           {
                   1253:           int nd;
                   1254:           int ndlen = 1;
                   1255:           GETCHARLEN(nd, nptr, ndlen);
1.2       misha    1256:           if (UCD_CATEGORY(nd) != ucp_M) break;
1.1       misha    1257:           ncount++;
                   1258:           nptr += ndlen;
                   1259:           }
                   1260:         count++;
                   1261:         ADD_NEW_DATA(-state_offset, count, ncount);
                   1262:         }
                   1263:       break;
                   1264: #endif
                   1265: 
                   1266:       /*-----------------------------------------------------------------*/
                   1267:       case OP_ANYNL_EXTRA + OP_TYPEPLUS:
                   1268:       case OP_ANYNL_EXTRA + OP_TYPEMINPLUS:
                   1269:       case OP_ANYNL_EXTRA + OP_TYPEPOSPLUS:
                   1270:       count = current_state->count;  /* Already matched */
                   1271:       if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
                   1272:       if (clen > 0)
                   1273:         {
                   1274:         int ncount = 0;
                   1275:         switch (c)
                   1276:           {
                   1277:           case 0x000b:
                   1278:           case 0x000c:
                   1279:           case 0x0085:
                   1280:           case 0x2028:
                   1281:           case 0x2029:
                   1282:           if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
                   1283:           goto ANYNL01;
                   1284: 
                   1285:           case 0x000d:
                   1286:           if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
                   1287:           /* Fall through */
                   1288: 
                   1289:           ANYNL01:
                   1290:           case 0x000a:
                   1291:           if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)
                   1292:             {
                   1293:             active_count--;           /* Remove non-match possibility */
                   1294:             next_active_state--;
                   1295:             }
                   1296:           count++;
                   1297:           ADD_NEW_DATA(-state_offset, count, ncount);
                   1298:           break;
                   1299: 
                   1300:           default:
                   1301:           break;
                   1302:           }
                   1303:         }
                   1304:       break;
                   1305: 
                   1306:       /*-----------------------------------------------------------------*/
                   1307:       case OP_VSPACE_EXTRA + OP_TYPEPLUS:
                   1308:       case OP_VSPACE_EXTRA + OP_TYPEMINPLUS:
                   1309:       case OP_VSPACE_EXTRA + OP_TYPEPOSPLUS:
                   1310:       count = current_state->count;  /* Already matched */
                   1311:       if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
                   1312:       if (clen > 0)
                   1313:         {
                   1314:         BOOL OK;
                   1315:         switch (c)
                   1316:           {
                   1317:           case 0x000a:
                   1318:           case 0x000b:
                   1319:           case 0x000c:
                   1320:           case 0x000d:
                   1321:           case 0x0085:
                   1322:           case 0x2028:
                   1323:           case 0x2029:
                   1324:           OK = TRUE;
                   1325:           break;
                   1326: 
                   1327:           default:
                   1328:           OK = FALSE;
                   1329:           break;
                   1330:           }
                   1331: 
                   1332:         if (OK == (d == OP_VSPACE))
                   1333:           {
                   1334:           if (count > 0 && codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSPLUS)
                   1335:             {
                   1336:             active_count--;           /* Remove non-match possibility */
                   1337:             next_active_state--;
                   1338:             }
                   1339:           count++;
                   1340:           ADD_NEW_DATA(-state_offset, count, 0);
                   1341:           }
                   1342:         }
                   1343:       break;
                   1344: 
                   1345:       /*-----------------------------------------------------------------*/
                   1346:       case OP_HSPACE_EXTRA + OP_TYPEPLUS:
                   1347:       case OP_HSPACE_EXTRA + OP_TYPEMINPLUS:
                   1348:       case OP_HSPACE_EXTRA + OP_TYPEPOSPLUS:
                   1349:       count = current_state->count;  /* Already matched */
                   1350:       if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
                   1351:       if (clen > 0)
                   1352:         {
                   1353:         BOOL OK;
                   1354:         switch (c)
                   1355:           {
                   1356:           case 0x09:      /* HT */
                   1357:           case 0x20:      /* SPACE */
                   1358:           case 0xa0:      /* NBSP */
                   1359:           case 0x1680:    /* OGHAM SPACE MARK */
                   1360:           case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
                   1361:           case 0x2000:    /* EN QUAD */
                   1362:           case 0x2001:    /* EM QUAD */
                   1363:           case 0x2002:    /* EN SPACE */
                   1364:           case 0x2003:    /* EM SPACE */
                   1365:           case 0x2004:    /* THREE-PER-EM SPACE */
                   1366:           case 0x2005:    /* FOUR-PER-EM SPACE */
                   1367:           case 0x2006:    /* SIX-PER-EM SPACE */
                   1368:           case 0x2007:    /* FIGURE SPACE */
                   1369:           case 0x2008:    /* PUNCTUATION SPACE */
                   1370:           case 0x2009:    /* THIN SPACE */
                   1371:           case 0x200A:    /* HAIR SPACE */
                   1372:           case 0x202f:    /* NARROW NO-BREAK SPACE */
                   1373:           case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
                   1374:           case 0x3000:    /* IDEOGRAPHIC SPACE */
                   1375:           OK = TRUE;
                   1376:           break;
                   1377: 
                   1378:           default:
                   1379:           OK = FALSE;
                   1380:           break;
                   1381:           }
                   1382: 
                   1383:         if (OK == (d == OP_HSPACE))
                   1384:           {
                   1385:           if (count > 0 && codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSPLUS)
                   1386:             {
                   1387:             active_count--;           /* Remove non-match possibility */
                   1388:             next_active_state--;
                   1389:             }
                   1390:           count++;
                   1391:           ADD_NEW_DATA(-state_offset, count, 0);
                   1392:           }
                   1393:         }
                   1394:       break;
                   1395: 
                   1396:       /*-----------------------------------------------------------------*/
                   1397: #ifdef SUPPORT_UCP
                   1398:       case OP_PROP_EXTRA + OP_TYPEQUERY:
                   1399:       case OP_PROP_EXTRA + OP_TYPEMINQUERY:
                   1400:       case OP_PROP_EXTRA + OP_TYPEPOSQUERY:
                   1401:       count = 4;
                   1402:       goto QS1;
                   1403: 
                   1404:       case OP_PROP_EXTRA + OP_TYPESTAR:
                   1405:       case OP_PROP_EXTRA + OP_TYPEMINSTAR:
                   1406:       case OP_PROP_EXTRA + OP_TYPEPOSSTAR:
                   1407:       count = 0;
                   1408: 
                   1409:       QS1:
                   1410: 
                   1411:       ADD_ACTIVE(state_offset + 4, 0);
                   1412:       if (clen > 0)
                   1413:         {
                   1414:         BOOL OK;
1.2       misha    1415:         const ucd_record * prop = GET_UCD(c);
1.1       misha    1416:         switch(code[2])
                   1417:           {
                   1418:           case PT_ANY:
                   1419:           OK = TRUE;
                   1420:           break;
                   1421: 
                   1422:           case PT_LAMP:
1.4     ! misha    1423:           OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
        !          1424:             prop->chartype == ucp_Lt;
1.1       misha    1425:           break;
                   1426: 
                   1427:           case PT_GC:
1.2       misha    1428:           OK = _pcre_ucp_gentype[prop->chartype] == code[3];
1.1       misha    1429:           break;
                   1430: 
                   1431:           case PT_PC:
1.2       misha    1432:           OK = prop->chartype == code[3];
1.1       misha    1433:           break;
                   1434: 
                   1435:           case PT_SC:
1.2       misha    1436:           OK = prop->script == code[3];
1.1       misha    1437:           break;
                   1438: 
1.4     ! misha    1439:           /* These are specials for combination cases. */
        !          1440: 
        !          1441:           case PT_ALNUM:
        !          1442:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
        !          1443:                _pcre_ucp_gentype[prop->chartype] == ucp_N;
        !          1444:           break;
        !          1445: 
        !          1446:           case PT_SPACE:    /* Perl space */
        !          1447:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
        !          1448:                c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
        !          1449:           break;
        !          1450: 
        !          1451:           case PT_PXSPACE:  /* POSIX space */
        !          1452:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
        !          1453:                c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
        !          1454:                c == CHAR_FF || c == CHAR_CR;
        !          1455:           break;
        !          1456: 
        !          1457:           case PT_WORD:
        !          1458:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
        !          1459:                _pcre_ucp_gentype[prop->chartype] == ucp_N ||
        !          1460:                c == CHAR_UNDERSCORE;
        !          1461:           break;
        !          1462: 
1.1       misha    1463:           /* Should never occur, but keep compilers from grumbling. */
                   1464: 
                   1465:           default:
                   1466:           OK = codevalue != OP_PROP;
                   1467:           break;
                   1468:           }
                   1469: 
                   1470:         if (OK == (d == OP_PROP))
                   1471:           {
                   1472:           if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSSTAR ||
                   1473:               codevalue == OP_PROP_EXTRA + OP_TYPEPOSQUERY)
                   1474:             {
                   1475:             active_count--;           /* Remove non-match possibility */
                   1476:             next_active_state--;
                   1477:             }
                   1478:           ADD_NEW(state_offset + count, 0);
                   1479:           }
                   1480:         }
                   1481:       break;
                   1482: 
                   1483:       /*-----------------------------------------------------------------*/
                   1484:       case OP_EXTUNI_EXTRA + OP_TYPEQUERY:
                   1485:       case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY:
                   1486:       case OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY:
                   1487:       count = 2;
                   1488:       goto QS2;
                   1489: 
                   1490:       case OP_EXTUNI_EXTRA + OP_TYPESTAR:
                   1491:       case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR:
                   1492:       case OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR:
                   1493:       count = 0;
                   1494: 
                   1495:       QS2:
                   1496: 
                   1497:       ADD_ACTIVE(state_offset + 2, 0);
1.2       misha    1498:       if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1.1       misha    1499:         {
                   1500:         const uschar *nptr = ptr + clen;
                   1501:         int ncount = 0;
                   1502:         if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||
                   1503:             codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)
                   1504:           {
                   1505:           active_count--;           /* Remove non-match possibility */
                   1506:           next_active_state--;
                   1507:           }
                   1508:         while (nptr < end_subject)
                   1509:           {
                   1510:           int nd;
                   1511:           int ndlen = 1;
                   1512:           GETCHARLEN(nd, nptr, ndlen);
1.2       misha    1513:           if (UCD_CATEGORY(nd) != ucp_M) break;
1.1       misha    1514:           ncount++;
                   1515:           nptr += ndlen;
                   1516:           }
                   1517:         ADD_NEW_DATA(-(state_offset + count), 0, ncount);
                   1518:         }
                   1519:       break;
                   1520: #endif
                   1521: 
                   1522:       /*-----------------------------------------------------------------*/
                   1523:       case OP_ANYNL_EXTRA + OP_TYPEQUERY:
                   1524:       case OP_ANYNL_EXTRA + OP_TYPEMINQUERY:
                   1525:       case OP_ANYNL_EXTRA + OP_TYPEPOSQUERY:
                   1526:       count = 2;
                   1527:       goto QS3;
                   1528: 
                   1529:       case OP_ANYNL_EXTRA + OP_TYPESTAR:
                   1530:       case OP_ANYNL_EXTRA + OP_TYPEMINSTAR:
                   1531:       case OP_ANYNL_EXTRA + OP_TYPEPOSSTAR:
                   1532:       count = 0;
                   1533: 
                   1534:       QS3:
                   1535:       ADD_ACTIVE(state_offset + 2, 0);
                   1536:       if (clen > 0)
                   1537:         {
                   1538:         int ncount = 0;
                   1539:         switch (c)
                   1540:           {
                   1541:           case 0x000b:
                   1542:           case 0x000c:
                   1543:           case 0x0085:
                   1544:           case 0x2028:
                   1545:           case 0x2029:
                   1546:           if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
                   1547:           goto ANYNL02;
                   1548: 
                   1549:           case 0x000d:
                   1550:           if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
                   1551:           /* Fall through */
                   1552: 
                   1553:           ANYNL02:
                   1554:           case 0x000a:
                   1555:           if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||
                   1556:               codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)
                   1557:             {
                   1558:             active_count--;           /* Remove non-match possibility */
                   1559:             next_active_state--;
                   1560:             }
                   1561:           ADD_NEW_DATA(-(state_offset + count), 0, ncount);
                   1562:           break;
                   1563: 
                   1564:           default:
                   1565:           break;
                   1566:           }
                   1567:         }
                   1568:       break;
                   1569: 
                   1570:       /*-----------------------------------------------------------------*/
                   1571:       case OP_VSPACE_EXTRA + OP_TYPEQUERY:
                   1572:       case OP_VSPACE_EXTRA + OP_TYPEMINQUERY:
                   1573:       case OP_VSPACE_EXTRA + OP_TYPEPOSQUERY:
                   1574:       count = 2;
                   1575:       goto QS4;
                   1576: 
                   1577:       case OP_VSPACE_EXTRA + OP_TYPESTAR:
                   1578:       case OP_VSPACE_EXTRA + OP_TYPEMINSTAR:
                   1579:       case OP_VSPACE_EXTRA + OP_TYPEPOSSTAR:
                   1580:       count = 0;
                   1581: 
                   1582:       QS4:
                   1583:       ADD_ACTIVE(state_offset + 2, 0);
                   1584:       if (clen > 0)
                   1585:         {
                   1586:         BOOL OK;
                   1587:         switch (c)
                   1588:           {
                   1589:           case 0x000a:
                   1590:           case 0x000b:
                   1591:           case 0x000c:
                   1592:           case 0x000d:
                   1593:           case 0x0085:
                   1594:           case 0x2028:
                   1595:           case 0x2029:
                   1596:           OK = TRUE;
                   1597:           break;
                   1598: 
                   1599:           default:
                   1600:           OK = FALSE;
                   1601:           break;
                   1602:           }
                   1603:         if (OK == (d == OP_VSPACE))
                   1604:           {
                   1605:           if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSSTAR ||
                   1606:               codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSQUERY)
                   1607:             {
                   1608:             active_count--;           /* Remove non-match possibility */
                   1609:             next_active_state--;
                   1610:             }
                   1611:           ADD_NEW_DATA(-(state_offset + count), 0, 0);
                   1612:           }
                   1613:         }
                   1614:       break;
                   1615: 
                   1616:       /*-----------------------------------------------------------------*/
                   1617:       case OP_HSPACE_EXTRA + OP_TYPEQUERY:
                   1618:       case OP_HSPACE_EXTRA + OP_TYPEMINQUERY:
                   1619:       case OP_HSPACE_EXTRA + OP_TYPEPOSQUERY:
                   1620:       count = 2;
                   1621:       goto QS5;
                   1622: 
                   1623:       case OP_HSPACE_EXTRA + OP_TYPESTAR:
                   1624:       case OP_HSPACE_EXTRA + OP_TYPEMINSTAR:
                   1625:       case OP_HSPACE_EXTRA + OP_TYPEPOSSTAR:
                   1626:       count = 0;
                   1627: 
                   1628:       QS5:
                   1629:       ADD_ACTIVE(state_offset + 2, 0);
                   1630:       if (clen > 0)
                   1631:         {
                   1632:         BOOL OK;
                   1633:         switch (c)
                   1634:           {
                   1635:           case 0x09:      /* HT */
                   1636:           case 0x20:      /* SPACE */
                   1637:           case 0xa0:      /* NBSP */
                   1638:           case 0x1680:    /* OGHAM SPACE MARK */
                   1639:           case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
                   1640:           case 0x2000:    /* EN QUAD */
                   1641:           case 0x2001:    /* EM QUAD */
                   1642:           case 0x2002:    /* EN SPACE */
                   1643:           case 0x2003:    /* EM SPACE */
                   1644:           case 0x2004:    /* THREE-PER-EM SPACE */
                   1645:           case 0x2005:    /* FOUR-PER-EM SPACE */
                   1646:           case 0x2006:    /* SIX-PER-EM SPACE */
                   1647:           case 0x2007:    /* FIGURE SPACE */
                   1648:           case 0x2008:    /* PUNCTUATION SPACE */
                   1649:           case 0x2009:    /* THIN SPACE */
                   1650:           case 0x200A:    /* HAIR SPACE */
                   1651:           case 0x202f:    /* NARROW NO-BREAK SPACE */
                   1652:           case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
                   1653:           case 0x3000:    /* IDEOGRAPHIC SPACE */
                   1654:           OK = TRUE;
                   1655:           break;
                   1656: 
                   1657:           default:
                   1658:           OK = FALSE;
                   1659:           break;
                   1660:           }
                   1661: 
                   1662:         if (OK == (d == OP_HSPACE))
                   1663:           {
                   1664:           if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSSTAR ||
                   1665:               codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSQUERY)
                   1666:             {
                   1667:             active_count--;           /* Remove non-match possibility */
                   1668:             next_active_state--;
                   1669:             }
                   1670:           ADD_NEW_DATA(-(state_offset + count), 0, 0);
                   1671:           }
                   1672:         }
                   1673:       break;
                   1674: 
                   1675:       /*-----------------------------------------------------------------*/
                   1676: #ifdef SUPPORT_UCP
                   1677:       case OP_PROP_EXTRA + OP_TYPEEXACT:
                   1678:       case OP_PROP_EXTRA + OP_TYPEUPTO:
                   1679:       case OP_PROP_EXTRA + OP_TYPEMINUPTO:
                   1680:       case OP_PROP_EXTRA + OP_TYPEPOSUPTO:
                   1681:       if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)
                   1682:         { ADD_ACTIVE(state_offset + 6, 0); }
                   1683:       count = current_state->count;  /* Number already matched */
                   1684:       if (clen > 0)
                   1685:         {
                   1686:         BOOL OK;
1.2       misha    1687:         const ucd_record * prop = GET_UCD(c);
1.1       misha    1688:         switch(code[4])
                   1689:           {
                   1690:           case PT_ANY:
                   1691:           OK = TRUE;
                   1692:           break;
                   1693: 
                   1694:           case PT_LAMP:
1.4     ! misha    1695:           OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
        !          1696:             prop->chartype == ucp_Lt;
1.1       misha    1697:           break;
                   1698: 
                   1699:           case PT_GC:
1.2       misha    1700:           OK = _pcre_ucp_gentype[prop->chartype] == code[5];
1.1       misha    1701:           break;
                   1702: 
                   1703:           case PT_PC:
1.2       misha    1704:           OK = prop->chartype == code[5];
1.1       misha    1705:           break;
                   1706: 
                   1707:           case PT_SC:
1.2       misha    1708:           OK = prop->script == code[5];
1.1       misha    1709:           break;
                   1710: 
1.4     ! misha    1711:           /* These are specials for combination cases. */
        !          1712: 
        !          1713:           case PT_ALNUM:
        !          1714:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
        !          1715:                _pcre_ucp_gentype[prop->chartype] == ucp_N;
        !          1716:           break;
        !          1717: 
        !          1718:           case PT_SPACE:    /* Perl space */
        !          1719:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
        !          1720:                c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
        !          1721:           break;
        !          1722: 
        !          1723:           case PT_PXSPACE:  /* POSIX space */
        !          1724:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_Z ||
        !          1725:                c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
        !          1726:                c == CHAR_FF || c == CHAR_CR;
        !          1727:           break;
        !          1728: 
        !          1729:           case PT_WORD:
        !          1730:           OK = _pcre_ucp_gentype[prop->chartype] == ucp_L ||
        !          1731:                _pcre_ucp_gentype[prop->chartype] == ucp_N ||
        !          1732:                c == CHAR_UNDERSCORE;
        !          1733:           break;
        !          1734: 
1.1       misha    1735:           /* Should never occur, but keep compilers from grumbling. */
                   1736: 
                   1737:           default:
                   1738:           OK = codevalue != OP_PROP;
                   1739:           break;
                   1740:           }
                   1741: 
                   1742:         if (OK == (d == OP_PROP))
                   1743:           {
                   1744:           if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSUPTO)
                   1745:             {
                   1746:             active_count--;           /* Remove non-match possibility */
                   1747:             next_active_state--;
                   1748:             }
                   1749:           if (++count >= GET2(code, 1))
                   1750:             { ADD_NEW(state_offset + 6, 0); }
                   1751:           else
                   1752:             { ADD_NEW(state_offset, count); }
                   1753:           }
                   1754:         }
                   1755:       break;
                   1756: 
                   1757:       /*-----------------------------------------------------------------*/
                   1758:       case OP_EXTUNI_EXTRA + OP_TYPEEXACT:
                   1759:       case OP_EXTUNI_EXTRA + OP_TYPEUPTO:
                   1760:       case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:
                   1761:       case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:
                   1762:       if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)
                   1763:         { ADD_ACTIVE(state_offset + 4, 0); }
                   1764:       count = current_state->count;  /* Number already matched */
1.2       misha    1765:       if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1.1       misha    1766:         {
                   1767:         const uschar *nptr = ptr + clen;
                   1768:         int ncount = 0;
                   1769:         if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)
                   1770:           {
                   1771:           active_count--;           /* Remove non-match possibility */
                   1772:           next_active_state--;
                   1773:           }
                   1774:         while (nptr < end_subject)
                   1775:           {
                   1776:           int nd;
                   1777:           int ndlen = 1;
                   1778:           GETCHARLEN(nd, nptr, ndlen);
1.2       misha    1779:           if (UCD_CATEGORY(nd) != ucp_M) break;
1.1       misha    1780:           ncount++;
                   1781:           nptr += ndlen;
                   1782:           }
                   1783:         if (++count >= GET2(code, 1))
                   1784:           { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }
                   1785:         else
                   1786:           { ADD_NEW_DATA(-state_offset, count, ncount); }
                   1787:         }
                   1788:       break;
                   1789: #endif
                   1790: 
                   1791:       /*-----------------------------------------------------------------*/
                   1792:       case OP_ANYNL_EXTRA + OP_TYPEEXACT:
                   1793:       case OP_ANYNL_EXTRA + OP_TYPEUPTO:
                   1794:       case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:
                   1795:       case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:
                   1796:       if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)
                   1797:         { ADD_ACTIVE(state_offset + 4, 0); }
                   1798:       count = current_state->count;  /* Number already matched */
                   1799:       if (clen > 0)
                   1800:         {
                   1801:         int ncount = 0;
                   1802:         switch (c)
                   1803:           {
                   1804:           case 0x000b:
                   1805:           case 0x000c:
                   1806:           case 0x0085:
                   1807:           case 0x2028:
                   1808:           case 0x2029:
                   1809:           if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
                   1810:           goto ANYNL03;
                   1811: 
                   1812:           case 0x000d:
                   1813:           if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
                   1814:           /* Fall through */
                   1815: 
                   1816:           ANYNL03:
                   1817:           case 0x000a:
                   1818:           if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)
                   1819:             {
                   1820:             active_count--;           /* Remove non-match possibility */
                   1821:             next_active_state--;
                   1822:             }
                   1823:           if (++count >= GET2(code, 1))
                   1824:             { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }
                   1825:           else
                   1826:             { ADD_NEW_DATA(-state_offset, count, ncount); }
                   1827:           break;
                   1828: 
                   1829:           default:
                   1830:           break;
                   1831:           }
                   1832:         }
                   1833:       break;
                   1834: 
                   1835:       /*-----------------------------------------------------------------*/
                   1836:       case OP_VSPACE_EXTRA + OP_TYPEEXACT:
                   1837:       case OP_VSPACE_EXTRA + OP_TYPEUPTO:
                   1838:       case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:
                   1839:       case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:
                   1840:       if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)
                   1841:         { ADD_ACTIVE(state_offset + 4, 0); }
                   1842:       count = current_state->count;  /* Number already matched */
                   1843:       if (clen > 0)
                   1844:         {
                   1845:         BOOL OK;
                   1846:         switch (c)
                   1847:           {
                   1848:           case 0x000a:
                   1849:           case 0x000b:
                   1850:           case 0x000c:
                   1851:           case 0x000d:
                   1852:           case 0x0085:
                   1853:           case 0x2028:
                   1854:           case 0x2029:
                   1855:           OK = TRUE;
                   1856:           break;
                   1857: 
                   1858:           default:
                   1859:           OK = FALSE;
                   1860:           }
                   1861: 
                   1862:         if (OK == (d == OP_VSPACE))
                   1863:           {
                   1864:           if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSUPTO)
                   1865:             {
                   1866:             active_count--;           /* Remove non-match possibility */
                   1867:             next_active_state--;
                   1868:             }
                   1869:           if (++count >= GET2(code, 1))
                   1870:             { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }
                   1871:           else
                   1872:             { ADD_NEW_DATA(-state_offset, count, 0); }
                   1873:           }
                   1874:         }
                   1875:       break;
                   1876: 
                   1877:       /*-----------------------------------------------------------------*/
                   1878:       case OP_HSPACE_EXTRA + OP_TYPEEXACT:
                   1879:       case OP_HSPACE_EXTRA + OP_TYPEUPTO:
                   1880:       case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:
                   1881:       case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:
                   1882:       if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)
                   1883:         { ADD_ACTIVE(state_offset + 4, 0); }
                   1884:       count = current_state->count;  /* Number already matched */
                   1885:       if (clen > 0)
                   1886:         {
                   1887:         BOOL OK;
                   1888:         switch (c)
                   1889:           {
                   1890:           case 0x09:      /* HT */
                   1891:           case 0x20:      /* SPACE */
                   1892:           case 0xa0:      /* NBSP */
                   1893:           case 0x1680:    /* OGHAM SPACE MARK */
                   1894:           case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
                   1895:           case 0x2000:    /* EN QUAD */
                   1896:           case 0x2001:    /* EM QUAD */
                   1897:           case 0x2002:    /* EN SPACE */
                   1898:           case 0x2003:    /* EM SPACE */
                   1899:           case 0x2004:    /* THREE-PER-EM SPACE */
                   1900:           case 0x2005:    /* FOUR-PER-EM SPACE */
                   1901:           case 0x2006:    /* SIX-PER-EM SPACE */
                   1902:           case 0x2007:    /* FIGURE SPACE */
                   1903:           case 0x2008:    /* PUNCTUATION SPACE */
                   1904:           case 0x2009:    /* THIN SPACE */
                   1905:           case 0x200A:    /* HAIR SPACE */
                   1906:           case 0x202f:    /* NARROW NO-BREAK SPACE */
                   1907:           case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
                   1908:           case 0x3000:    /* IDEOGRAPHIC SPACE */
                   1909:           OK = TRUE;
                   1910:           break;
                   1911: 
                   1912:           default:
                   1913:           OK = FALSE;
                   1914:           break;
                   1915:           }
                   1916: 
                   1917:         if (OK == (d == OP_HSPACE))
                   1918:           {
                   1919:           if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSUPTO)
                   1920:             {
                   1921:             active_count--;           /* Remove non-match possibility */
                   1922:             next_active_state--;
                   1923:             }
                   1924:           if (++count >= GET2(code, 1))
                   1925:             { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }
                   1926:           else
                   1927:             { ADD_NEW_DATA(-state_offset, count, 0); }
                   1928:           }
                   1929:         }
                   1930:       break;
                   1931: 
                   1932: /* ========================================================================== */
                   1933:       /* These opcodes are followed by a character that is usually compared
                   1934:       to the current subject character; it is loaded into d. We still get
                   1935:       here even if there is no subject character, because in some cases zero
                   1936:       repetitions are permitted. */
                   1937: 
                   1938:       /*-----------------------------------------------------------------*/
                   1939:       case OP_CHAR:
                   1940:       if (clen > 0 && c == d) { ADD_NEW(state_offset + dlen + 1, 0); }
                   1941:       break;
                   1942: 
                   1943:       /*-----------------------------------------------------------------*/
                   1944:       case OP_CHARNC:
                   1945:       if (clen == 0) break;
                   1946: 
                   1947: #ifdef SUPPORT_UTF8
                   1948:       if (utf8)
                   1949:         {
                   1950:         if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else
                   1951:           {
                   1952:           unsigned int othercase;
                   1953:           if (c < 128) othercase = fcc[c]; else
                   1954: 
                   1955:           /* If we have Unicode property support, we can use it to test the
                   1956:           other case of the character. */
                   1957: 
                   1958: #ifdef SUPPORT_UCP
1.2       misha    1959:           othercase = UCD_OTHERCASE(c);
1.1       misha    1960: #else
                   1961:           othercase = NOTACHAR;
                   1962: #endif
                   1963: 
                   1964:           if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }
                   1965:           }
                   1966:         }
                   1967:       else
                   1968: #endif  /* SUPPORT_UTF8 */
                   1969: 
                   1970:       /* Non-UTF-8 mode */
                   1971:         {
                   1972:         if (lcc[c] == lcc[d]) { ADD_NEW(state_offset + 2, 0); }
                   1973:         }
                   1974:       break;
                   1975: 
                   1976: 
                   1977: #ifdef SUPPORT_UCP
                   1978:       /*-----------------------------------------------------------------*/
                   1979:       /* This is a tricky one because it can match more than one character.
                   1980:       Find out how many characters to skip, and then set up a negative state
                   1981:       to wait for them to pass before continuing. */
                   1982: 
                   1983:       case OP_EXTUNI:
1.2       misha    1984:       if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
1.1       misha    1985:         {
                   1986:         const uschar *nptr = ptr + clen;
                   1987:         int ncount = 0;
                   1988:         while (nptr < end_subject)
                   1989:           {
                   1990:           int nclen = 1;
                   1991:           GETCHARLEN(c, nptr, nclen);
1.2       misha    1992:           if (UCD_CATEGORY(c) != ucp_M) break;
1.1       misha    1993:           ncount++;
                   1994:           nptr += nclen;
                   1995:           }
                   1996:         ADD_NEW_DATA(-(state_offset + 1), 0, ncount);
                   1997:         }
                   1998:       break;
                   1999: #endif
                   2000: 
                   2001:       /*-----------------------------------------------------------------*/
                   2002:       /* This is a tricky like EXTUNI because it too can match more than one
                   2003:       character (when CR is followed by LF). In this case, set up a negative
                   2004:       state to wait for one character to pass before continuing. */
                   2005: 
                   2006:       case OP_ANYNL:
                   2007:       if (clen > 0) switch(c)
                   2008:         {
                   2009:         case 0x000b:
                   2010:         case 0x000c:
                   2011:         case 0x0085:
                   2012:         case 0x2028:
                   2013:         case 0x2029:
                   2014:         if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
                   2015: 
                   2016:         case 0x000a:
                   2017:         ADD_NEW(state_offset + 1, 0);
                   2018:         break;
                   2019: 
                   2020:         case 0x000d:
                   2021:         if (ptr + 1 < end_subject && ptr[1] == 0x0a)
                   2022:           {
                   2023:           ADD_NEW_DATA(-(state_offset + 1), 0, 1);
                   2024:           }
                   2025:         else
                   2026:           {
                   2027:           ADD_NEW(state_offset + 1, 0);
                   2028:           }
                   2029:         break;
                   2030:         }
                   2031:       break;
                   2032: 
                   2033:       /*-----------------------------------------------------------------*/
                   2034:       case OP_NOT_VSPACE:
                   2035:       if (clen > 0) switch(c)
                   2036:         {
                   2037:         case 0x000a:
                   2038:         case 0x000b:
                   2039:         case 0x000c:
                   2040:         case 0x000d:
                   2041:         case 0x0085:
                   2042:         case 0x2028:
                   2043:         case 0x2029:
                   2044:         break;
                   2045: 
                   2046:         default:
                   2047:         ADD_NEW(state_offset + 1, 0);
                   2048:         break;
                   2049:         }
                   2050:       break;
                   2051: 
                   2052:       /*-----------------------------------------------------------------*/
                   2053:       case OP_VSPACE:
                   2054:       if (clen > 0) switch(c)
                   2055:         {
                   2056:         case 0x000a:
                   2057:         case 0x000b:
                   2058:         case 0x000c:
                   2059:         case 0x000d:
                   2060:         case 0x0085:
                   2061:         case 0x2028:
                   2062:         case 0x2029:
                   2063:         ADD_NEW(state_offset + 1, 0);
                   2064:         break;
                   2065: 
                   2066:         default: break;
                   2067:         }
                   2068:       break;
                   2069: 
                   2070:       /*-----------------------------------------------------------------*/
                   2071:       case OP_NOT_HSPACE:
                   2072:       if (clen > 0) switch(c)
                   2073:         {
                   2074:         case 0x09:      /* HT */
                   2075:         case 0x20:      /* SPACE */
                   2076:         case 0xa0:      /* NBSP */
                   2077:         case 0x1680:    /* OGHAM SPACE MARK */
                   2078:         case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
                   2079:         case 0x2000:    /* EN QUAD */
                   2080:         case 0x2001:    /* EM QUAD */
                   2081:         case 0x2002:    /* EN SPACE */
                   2082:         case 0x2003:    /* EM SPACE */
                   2083:         case 0x2004:    /* THREE-PER-EM SPACE */
                   2084:         case 0x2005:    /* FOUR-PER-EM SPACE */
                   2085:         case 0x2006:    /* SIX-PER-EM SPACE */
                   2086:         case 0x2007:    /* FIGURE SPACE */
                   2087:         case 0x2008:    /* PUNCTUATION SPACE */
                   2088:         case 0x2009:    /* THIN SPACE */
                   2089:         case 0x200A:    /* HAIR SPACE */
                   2090:         case 0x202f:    /* NARROW NO-BREAK SPACE */
                   2091:         case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
                   2092:         case 0x3000:    /* IDEOGRAPHIC SPACE */
                   2093:         break;
                   2094: 
                   2095:         default:
                   2096:         ADD_NEW(state_offset + 1, 0);
                   2097:         break;
                   2098:         }
                   2099:       break;
                   2100: 
                   2101:       /*-----------------------------------------------------------------*/
                   2102:       case OP_HSPACE:
                   2103:       if (clen > 0) switch(c)
                   2104:         {
                   2105:         case 0x09:      /* HT */
                   2106:         case 0x20:      /* SPACE */
                   2107:         case 0xa0:      /* NBSP */
                   2108:         case 0x1680:    /* OGHAM SPACE MARK */
                   2109:         case 0x180e:    /* MONGOLIAN VOWEL SEPARATOR */
                   2110:         case 0x2000:    /* EN QUAD */
                   2111:         case 0x2001:    /* EM QUAD */
                   2112:         case 0x2002:    /* EN SPACE */
                   2113:         case 0x2003:    /* EM SPACE */
                   2114:         case 0x2004:    /* THREE-PER-EM SPACE */
                   2115:         case 0x2005:    /* FOUR-PER-EM SPACE */
                   2116:         case 0x2006:    /* SIX-PER-EM SPACE */
                   2117:         case 0x2007:    /* FIGURE SPACE */
                   2118:         case 0x2008:    /* PUNCTUATION SPACE */
                   2119:         case 0x2009:    /* THIN SPACE */
                   2120:         case 0x200A:    /* HAIR SPACE */
                   2121:         case 0x202f:    /* NARROW NO-BREAK SPACE */
                   2122:         case 0x205f:    /* MEDIUM MATHEMATICAL SPACE */
                   2123:         case 0x3000:    /* IDEOGRAPHIC SPACE */
                   2124:         ADD_NEW(state_offset + 1, 0);
                   2125:         break;
                   2126:         }
                   2127:       break;
                   2128: 
                   2129:       /*-----------------------------------------------------------------*/
                   2130:       /* Match a negated single character. This is only used for one-byte
                   2131:       characters, that is, we know that d < 256. The character we are
                   2132:       checking (c) can be multibyte. */
                   2133: 
                   2134:       case OP_NOT:
                   2135:       if (clen > 0)
                   2136:         {
                   2137:         unsigned int otherd = ((ims & PCRE_CASELESS) != 0)? fcc[d] : d;
                   2138:         if (c != d && c != otherd) { ADD_NEW(state_offset + dlen + 1, 0); }
                   2139:         }
                   2140:       break;
                   2141: 
                   2142:       /*-----------------------------------------------------------------*/
                   2143:       case OP_PLUS:
                   2144:       case OP_MINPLUS:
                   2145:       case OP_POSPLUS:
                   2146:       case OP_NOTPLUS:
                   2147:       case OP_NOTMINPLUS:
                   2148:       case OP_NOTPOSPLUS:
                   2149:       count = current_state->count;  /* Already matched */
                   2150:       if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }
                   2151:       if (clen > 0)
                   2152:         {
                   2153:         unsigned int otherd = NOTACHAR;
                   2154:         if ((ims & PCRE_CASELESS) != 0)
                   2155:           {
                   2156: #ifdef SUPPORT_UTF8
                   2157:           if (utf8 && d >= 128)
                   2158:             {
                   2159: #ifdef SUPPORT_UCP
1.2       misha    2160:             otherd = UCD_OTHERCASE(d);
1.1       misha    2161: #endif  /* SUPPORT_UCP */
                   2162:             }
                   2163:           else
                   2164: #endif  /* SUPPORT_UTF8 */
                   2165:           otherd = fcc[d];
                   2166:           }
                   2167:         if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
                   2168:           {
                   2169:           if (count > 0 &&
                   2170:               (codevalue == OP_POSPLUS || codevalue == OP_NOTPOSPLUS))
                   2171:             {
                   2172:             active_count--;             /* Remove non-match possibility */
                   2173:             next_active_state--;
                   2174:             }
                   2175:           count++;
                   2176:           ADD_NEW(state_offset, count);
                   2177:           }
                   2178:         }
                   2179:       break;
                   2180: 
                   2181:       /*-----------------------------------------------------------------*/
                   2182:       case OP_QUERY:
                   2183:       case OP_MINQUERY:
                   2184:       case OP_POSQUERY:
                   2185:       case OP_NOTQUERY:
                   2186:       case OP_NOTMINQUERY:
                   2187:       case OP_NOTPOSQUERY:
                   2188:       ADD_ACTIVE(state_offset + dlen + 1, 0);
                   2189:       if (clen > 0)
                   2190:         {
                   2191:         unsigned int otherd = NOTACHAR;
                   2192:         if ((ims & PCRE_CASELESS) != 0)
                   2193:           {
                   2194: #ifdef SUPPORT_UTF8
                   2195:           if (utf8 && d >= 128)
                   2196:             {
                   2197: #ifdef SUPPORT_UCP
1.2       misha    2198:             otherd = UCD_OTHERCASE(d);
1.1       misha    2199: #endif  /* SUPPORT_UCP */
                   2200:             }
                   2201:           else
                   2202: #endif  /* SUPPORT_UTF8 */
                   2203:           otherd = fcc[d];
                   2204:           }
                   2205:         if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
                   2206:           {
                   2207:           if (codevalue == OP_POSQUERY || codevalue == OP_NOTPOSQUERY)
                   2208:             {
                   2209:             active_count--;            /* Remove non-match possibility */
                   2210:             next_active_state--;
                   2211:             }
                   2212:           ADD_NEW(state_offset + dlen + 1, 0);
                   2213:           }
                   2214:         }
                   2215:       break;
                   2216: 
                   2217:       /*-----------------------------------------------------------------*/
                   2218:       case OP_STAR:
                   2219:       case OP_MINSTAR:
                   2220:       case OP_POSSTAR:
                   2221:       case OP_NOTSTAR:
                   2222:       case OP_NOTMINSTAR:
                   2223:       case OP_NOTPOSSTAR:
                   2224:       ADD_ACTIVE(state_offset + dlen + 1, 0);
                   2225:       if (clen > 0)
                   2226:         {
                   2227:         unsigned int otherd = NOTACHAR;
                   2228:         if ((ims & PCRE_CASELESS) != 0)
                   2229:           {
                   2230: #ifdef SUPPORT_UTF8
                   2231:           if (utf8 && d >= 128)
                   2232:             {
                   2233: #ifdef SUPPORT_UCP
1.2       misha    2234:             otherd = UCD_OTHERCASE(d);
1.1       misha    2235: #endif  /* SUPPORT_UCP */
                   2236:             }
                   2237:           else
                   2238: #endif  /* SUPPORT_UTF8 */
                   2239:           otherd = fcc[d];
                   2240:           }
                   2241:         if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
                   2242:           {
                   2243:           if (codevalue == OP_POSSTAR || codevalue == OP_NOTPOSSTAR)
                   2244:             {
                   2245:             active_count--;            /* Remove non-match possibility */
                   2246:             next_active_state--;
                   2247:             }
                   2248:           ADD_NEW(state_offset, 0);
                   2249:           }
                   2250:         }
                   2251:       break;
                   2252: 
                   2253:       /*-----------------------------------------------------------------*/
                   2254:       case OP_EXACT:
                   2255:       case OP_NOTEXACT:
                   2256:       count = current_state->count;  /* Number already matched */
                   2257:       if (clen > 0)
                   2258:         {
                   2259:         unsigned int otherd = NOTACHAR;
                   2260:         if ((ims & PCRE_CASELESS) != 0)
                   2261:           {
                   2262: #ifdef SUPPORT_UTF8
                   2263:           if (utf8 && d >= 128)
                   2264:             {
                   2265: #ifdef SUPPORT_UCP
1.2       misha    2266:             otherd = UCD_OTHERCASE(d);
1.1       misha    2267: #endif  /* SUPPORT_UCP */
                   2268:             }
                   2269:           else
                   2270: #endif  /* SUPPORT_UTF8 */
                   2271:           otherd = fcc[d];
                   2272:           }
                   2273:         if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
                   2274:           {
                   2275:           if (++count >= GET2(code, 1))
                   2276:             { ADD_NEW(state_offset + dlen + 3, 0); }
                   2277:           else
                   2278:             { ADD_NEW(state_offset, count); }
                   2279:           }
                   2280:         }
                   2281:       break;
                   2282: 
                   2283:       /*-----------------------------------------------------------------*/
                   2284:       case OP_UPTO:
                   2285:       case OP_MINUPTO:
                   2286:       case OP_POSUPTO:
                   2287:       case OP_NOTUPTO:
                   2288:       case OP_NOTMINUPTO:
                   2289:       case OP_NOTPOSUPTO:
                   2290:       ADD_ACTIVE(state_offset + dlen + 3, 0);
                   2291:       count = current_state->count;  /* Number already matched */
                   2292:       if (clen > 0)
                   2293:         {
                   2294:         unsigned int otherd = NOTACHAR;
                   2295:         if ((ims & PCRE_CASELESS) != 0)
                   2296:           {
                   2297: #ifdef SUPPORT_UTF8
                   2298:           if (utf8 && d >= 128)
                   2299:             {
                   2300: #ifdef SUPPORT_UCP
1.2       misha    2301:             otherd = UCD_OTHERCASE(d);
1.1       misha    2302: #endif  /* SUPPORT_UCP */
                   2303:             }
                   2304:           else
                   2305: #endif  /* SUPPORT_UTF8 */
                   2306:           otherd = fcc[d];
                   2307:           }
                   2308:         if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
                   2309:           {
                   2310:           if (codevalue == OP_POSUPTO || codevalue == OP_NOTPOSUPTO)
                   2311:             {
                   2312:             active_count--;             /* Remove non-match possibility */
                   2313:             next_active_state--;
                   2314:             }
                   2315:           if (++count >= GET2(code, 1))
                   2316:             { ADD_NEW(state_offset + dlen + 3, 0); }
                   2317:           else
                   2318:             { ADD_NEW(state_offset, count); }
                   2319:           }
                   2320:         }
                   2321:       break;
                   2322: 
                   2323: 
                   2324: /* ========================================================================== */
                   2325:       /* These are the class-handling opcodes */
                   2326: 
                   2327:       case OP_CLASS:
                   2328:       case OP_NCLASS:
                   2329:       case OP_XCLASS:
                   2330:         {
                   2331:         BOOL isinclass = FALSE;
                   2332:         int next_state_offset;
                   2333:         const uschar *ecode;
                   2334: 
                   2335:         /* For a simple class, there is always just a 32-byte table, and we
                   2336:         can set isinclass from it. */
                   2337: 
                   2338:         if (codevalue != OP_XCLASS)
                   2339:           {
                   2340:           ecode = code + 33;
                   2341:           if (clen > 0)
                   2342:             {
                   2343:             isinclass = (c > 255)? (codevalue == OP_NCLASS) :
                   2344:               ((code[1 + c/8] & (1 << (c&7))) != 0);
                   2345:             }
                   2346:           }
                   2347: 
                   2348:         /* An extended class may have a table or a list of single characters,
                   2349:         ranges, or both, and it may be positive or negative. There's a
                   2350:         function that sorts all this out. */
                   2351: 
                   2352:         else
                   2353:          {
                   2354:          ecode = code + GET(code, 1);
                   2355:          if (clen > 0) isinclass = _pcre_xclass(c, code + 1 + LINK_SIZE);
                   2356:          }
                   2357: 
                   2358:         /* At this point, isinclass is set for all kinds of class, and ecode
                   2359:         points to the byte after the end of the class. If there is a
                   2360:         quantifier, this is where it will be. */
                   2361: 
1.4     ! misha    2362:         next_state_offset = (int)(ecode - start_code);
1.1       misha    2363: 
                   2364:         switch (*ecode)
                   2365:           {
                   2366:           case OP_CRSTAR:
                   2367:           case OP_CRMINSTAR:
                   2368:           ADD_ACTIVE(next_state_offset + 1, 0);
                   2369:           if (isinclass) { ADD_NEW(state_offset, 0); }
                   2370:           break;
                   2371: 
                   2372:           case OP_CRPLUS:
                   2373:           case OP_CRMINPLUS:
                   2374:           count = current_state->count;  /* Already matched */
                   2375:           if (count > 0) { ADD_ACTIVE(next_state_offset + 1, 0); }
                   2376:           if (isinclass) { count++; ADD_NEW(state_offset, count); }
                   2377:           break;
                   2378: 
                   2379:           case OP_CRQUERY:
                   2380:           case OP_CRMINQUERY:
                   2381:           ADD_ACTIVE(next_state_offset + 1, 0);
                   2382:           if (isinclass) { ADD_NEW(next_state_offset + 1, 0); }
                   2383:           break;
                   2384: 
                   2385:           case OP_CRRANGE:
                   2386:           case OP_CRMINRANGE:
                   2387:           count = current_state->count;  /* Already matched */
                   2388:           if (count >= GET2(ecode, 1))
                   2389:             { ADD_ACTIVE(next_state_offset + 5, 0); }
                   2390:           if (isinclass)
                   2391:             {
                   2392:             int max = GET2(ecode, 3);
                   2393:             if (++count >= max && max != 0)   /* Max 0 => no limit */
                   2394:               { ADD_NEW(next_state_offset + 5, 0); }
                   2395:             else
                   2396:               { ADD_NEW(state_offset, count); }
                   2397:             }
                   2398:           break;
                   2399: 
                   2400:           default:
                   2401:           if (isinclass) { ADD_NEW(next_state_offset, 0); }
                   2402:           break;
                   2403:           }
                   2404:         }
                   2405:       break;
                   2406: 
                   2407: /* ========================================================================== */
                   2408:       /* These are the opcodes for fancy brackets of various kinds. We have
1.4     ! misha    2409:       to use recursion in order to handle them. The "always failing" assertion
        !          2410:       (?!) is optimised to OP_FAIL when compiling, so we have to support that,
1.1       misha    2411:       though the other "backtracking verbs" are not supported. */
                   2412: 
                   2413:       case OP_FAIL:
1.4     ! misha    2414:       forced_fail++;    /* Count FAILs for multiple states */
1.1       misha    2415:       break;
                   2416: 
                   2417:       case OP_ASSERT:
                   2418:       case OP_ASSERT_NOT:
                   2419:       case OP_ASSERTBACK:
                   2420:       case OP_ASSERTBACK_NOT:
                   2421:         {
                   2422:         int rc;
                   2423:         int local_offsets[2];
                   2424:         int local_workspace[1000];
                   2425:         const uschar *endasscode = code + GET(code, 1);
                   2426: 
                   2427:         while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
                   2428: 
                   2429:         rc = internal_dfa_exec(
                   2430:           md,                                   /* static match data */
                   2431:           code,                                 /* this subexpression's code */
                   2432:           ptr,                                  /* where we currently are */
1.4     ! misha    2433:           (int)(ptr - start_subject),           /* start offset */
1.1       misha    2434:           local_offsets,                        /* offset vector */
                   2435:           sizeof(local_offsets)/sizeof(int),    /* size of same */
                   2436:           local_workspace,                      /* workspace vector */
                   2437:           sizeof(local_workspace)/sizeof(int),  /* size of same */
                   2438:           ims,                                  /* the current ims flags */
                   2439:           rlevel,                               /* function recursion level */
                   2440:           recursing);                           /* pass on regex recursion */
                   2441: 
1.4     ! misha    2442:         if (rc == PCRE_ERROR_DFA_UITEM) return rc;
1.1       misha    2443:         if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))
1.4     ! misha    2444:             { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); }
1.1       misha    2445:         }
                   2446:       break;
                   2447: 
                   2448:       /*-----------------------------------------------------------------*/
                   2449:       case OP_COND:
                   2450:       case OP_SCOND:
                   2451:         {
                   2452:         int local_offsets[1000];
                   2453:         int local_workspace[1000];
1.3       misha    2454:         int codelink = GET(code, 1);
                   2455:         int condcode;
                   2456: 
                   2457:         /* Because of the way auto-callout works during compile, a callout item
                   2458:         is inserted between OP_COND and an assertion condition. This does not
                   2459:         happen for the other conditions. */
                   2460: 
                   2461:         if (code[LINK_SIZE+1] == OP_CALLOUT)
                   2462:           {
                   2463:           rrc = 0;
                   2464:           if (pcre_callout != NULL)
                   2465:             {
                   2466:             pcre_callout_block cb;
                   2467:             cb.version          = 1;   /* Version 1 of the callout block */
                   2468:             cb.callout_number   = code[LINK_SIZE+2];
                   2469:             cb.offset_vector    = offsets;
                   2470:             cb.subject          = (PCRE_SPTR)start_subject;
1.4     ! misha    2471:             cb.subject_length   = (int)(end_subject - start_subject);
        !          2472:             cb.start_match      = (int)(current_subject - start_subject);
        !          2473:             cb.current_position = (int)(ptr - start_subject);
1.3       misha    2474:             cb.pattern_position = GET(code, LINK_SIZE + 3);
                   2475:             cb.next_item_length = GET(code, 3 + 2*LINK_SIZE);
                   2476:             cb.capture_top      = 1;
                   2477:             cb.capture_last     = -1;
                   2478:             cb.callout_data     = md->callout_data;
                   2479:             if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */
                   2480:             }
                   2481:           if (rrc > 0) break;                      /* Fail this thread */
                   2482:           code += _pcre_OP_lengths[OP_CALLOUT];    /* Skip callout data */
                   2483:           }
                   2484: 
                   2485:         condcode = code[LINK_SIZE+1];
1.1       misha    2486: 
                   2487:         /* Back reference conditions are not supported */
                   2488: 
1.4     ! misha    2489:         if (condcode == OP_CREF || condcode == OP_NCREF)
        !          2490:           return PCRE_ERROR_DFA_UCOND;
1.1       misha    2491: 
                   2492:         /* The DEFINE condition is always false */
                   2493: 
                   2494:         if (condcode == OP_DEF)
1.3       misha    2495:           { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
1.1       misha    2496: 
                   2497:         /* The only supported version of OP_RREF is for the value RREF_ANY,
                   2498:         which means "test if in any recursion". We can't test for specifically
                   2499:         recursed groups. */
                   2500: 
1.4     ! misha    2501:         else if (condcode == OP_RREF || condcode == OP_NRREF)
1.1       misha    2502:           {
                   2503:           int value = GET2(code, LINK_SIZE+2);
                   2504:           if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
1.3       misha    2505:           if (recursing > 0)
                   2506:             { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); }
                   2507:           else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
1.1       misha    2508:           }
                   2509: 
                   2510:         /* Otherwise, the condition is an assertion */
                   2511: 
                   2512:         else
                   2513:           {
                   2514:           int rc;
                   2515:           const uschar *asscode = code + LINK_SIZE + 1;
                   2516:           const uschar *endasscode = asscode + GET(asscode, 1);
                   2517: 
                   2518:           while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
                   2519: 
                   2520:           rc = internal_dfa_exec(
                   2521:             md,                                   /* fixed match data */
                   2522:             asscode,                              /* this subexpression's code */
                   2523:             ptr,                                  /* where we currently are */
1.4     ! misha    2524:             (int)(ptr - start_subject),           /* start offset */
1.1       misha    2525:             local_offsets,                        /* offset vector */
                   2526:             sizeof(local_offsets)/sizeof(int),    /* size of same */
                   2527:             local_workspace,                      /* workspace vector */
                   2528:             sizeof(local_workspace)/sizeof(int),  /* size of same */
                   2529:             ims,                                  /* the current ims flags */
                   2530:             rlevel,                               /* function recursion level */
                   2531:             recursing);                           /* pass on regex recursion */
                   2532: 
1.4     ! misha    2533:           if (rc == PCRE_ERROR_DFA_UITEM) return rc;
1.1       misha    2534:           if ((rc >= 0) ==
                   2535:                 (condcode == OP_ASSERT || condcode == OP_ASSERTBACK))
1.4     ! misha    2536:             { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); }
1.1       misha    2537:           else
1.3       misha    2538:             { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
1.1       misha    2539:           }
                   2540:         }
                   2541:       break;
                   2542: 
                   2543:       /*-----------------------------------------------------------------*/
                   2544:       case OP_RECURSE:
                   2545:         {
                   2546:         int local_offsets[1000];
                   2547:         int local_workspace[1000];
                   2548:         int rc;
                   2549: 
                   2550:         DPRINTF(("%.*sStarting regex recursion %d\n", rlevel*2-2, SP,
                   2551:           recursing + 1));
                   2552: 
                   2553:         rc = internal_dfa_exec(
                   2554:           md,                                   /* fixed match data */
                   2555:           start_code + GET(code, 1),            /* this subexpression's code */
                   2556:           ptr,                                  /* where we currently are */
1.4     ! misha    2557:           (int)(ptr - start_subject),           /* start offset */
1.1       misha    2558:           local_offsets,                        /* offset vector */
                   2559:           sizeof(local_offsets)/sizeof(int),    /* size of same */
                   2560:           local_workspace,                      /* workspace vector */
                   2561:           sizeof(local_workspace)/sizeof(int),  /* size of same */
                   2562:           ims,                                  /* the current ims flags */
                   2563:           rlevel,                               /* function recursion level */
                   2564:           recursing + 1);                       /* regex recurse level */
                   2565: 
                   2566:         DPRINTF(("%.*sReturn from regex recursion %d: rc=%d\n", rlevel*2-2, SP,
                   2567:           recursing + 1, rc));
                   2568: 
                   2569:         /* Ran out of internal offsets */
                   2570: 
                   2571:         if (rc == 0) return PCRE_ERROR_DFA_RECURSE;
                   2572: 
                   2573:         /* For each successful matched substring, set up the next state with a
                   2574:         count of characters to skip before trying it. Note that the count is in
                   2575:         characters, not bytes. */
                   2576: 
                   2577:         if (rc > 0)
                   2578:           {
                   2579:           for (rc = rc*2 - 2; rc >= 0; rc -= 2)
                   2580:             {
                   2581:             const uschar *p = start_subject + local_offsets[rc];
                   2582:             const uschar *pp = start_subject + local_offsets[rc+1];
                   2583:             int charcount = local_offsets[rc+1] - local_offsets[rc];
                   2584:             while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;
                   2585:             if (charcount > 0)
                   2586:               {
                   2587:               ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1));
                   2588:               }
                   2589:             else
                   2590:               {
                   2591:               ADD_ACTIVE(state_offset + LINK_SIZE + 1, 0);
                   2592:               }
                   2593:             }
                   2594:           }
                   2595:         else if (rc != PCRE_ERROR_NOMATCH) return rc;
                   2596:         }
                   2597:       break;
                   2598: 
                   2599:       /*-----------------------------------------------------------------*/
                   2600:       case OP_ONCE:
                   2601:         {
                   2602:         int local_offsets[2];
                   2603:         int local_workspace[1000];
                   2604: 
                   2605:         int rc = internal_dfa_exec(
                   2606:           md,                                   /* fixed match data */
                   2607:           code,                                 /* this subexpression's code */
                   2608:           ptr,                                  /* where we currently are */
1.4     ! misha    2609:           (int)(ptr - start_subject),           /* start offset */
1.1       misha    2610:           local_offsets,                        /* offset vector */
                   2611:           sizeof(local_offsets)/sizeof(int),    /* size of same */
                   2612:           local_workspace,                      /* workspace vector */
                   2613:           sizeof(local_workspace)/sizeof(int),  /* size of same */
                   2614:           ims,                                  /* the current ims flags */
                   2615:           rlevel,                               /* function recursion level */
                   2616:           recursing);                           /* pass on regex recursion */
                   2617: 
                   2618:         if (rc >= 0)
                   2619:           {
                   2620:           const uschar *end_subpattern = code;
                   2621:           int charcount = local_offsets[1] - local_offsets[0];
                   2622:           int next_state_offset, repeat_state_offset;
                   2623: 
                   2624:           do { end_subpattern += GET(end_subpattern, 1); }
                   2625:             while (*end_subpattern == OP_ALT);
1.4     ! misha    2626:           next_state_offset =
        !          2627:             (int)(end_subpattern - start_code + LINK_SIZE + 1);
1.1       misha    2628: 
                   2629:           /* If the end of this subpattern is KETRMAX or KETRMIN, we must
                   2630:           arrange for the repeat state also to be added to the relevant list.
                   2631:           Calculate the offset, or set -1 for no repeat. */
                   2632: 
                   2633:           repeat_state_offset = (*end_subpattern == OP_KETRMAX ||
                   2634:                                  *end_subpattern == OP_KETRMIN)?
1.4     ! misha    2635:             (int)(end_subpattern - start_code - GET(end_subpattern, 1)) : -1;
1.1       misha    2636: 
                   2637:           /* If we have matched an empty string, add the next state at the
                   2638:           current character pointer. This is important so that the duplicate
                   2639:           checking kicks in, which is what breaks infinite loops that match an
                   2640:           empty string. */
                   2641: 
                   2642:           if (charcount == 0)
                   2643:             {
                   2644:             ADD_ACTIVE(next_state_offset, 0);
                   2645:             }
                   2646: 
                   2647:           /* Optimization: if there are no more active states, and there
                   2648:           are no new states yet set up, then skip over the subject string
                   2649:           right here, to save looping. Otherwise, set up the new state to swing
                   2650:           into action when the end of the substring is reached. */
                   2651: 
                   2652:           else if (i + 1 >= active_count && new_count == 0)
                   2653:             {
                   2654:             ptr += charcount;
                   2655:             clen = 0;
                   2656:             ADD_NEW(next_state_offset, 0);
                   2657: 
                   2658:             /* If we are adding a repeat state at the new character position,
                   2659:             we must fudge things so that it is the only current state.
                   2660:             Otherwise, it might be a duplicate of one we processed before, and
                   2661:             that would cause it to be skipped. */
                   2662: 
                   2663:             if (repeat_state_offset >= 0)
                   2664:               {
                   2665:               next_active_state = active_states;
                   2666:               active_count = 0;
                   2667:               i = -1;
                   2668:               ADD_ACTIVE(repeat_state_offset, 0);
                   2669:               }
                   2670:             }
                   2671:           else
                   2672:             {
                   2673:             const uschar *p = start_subject + local_offsets[0];
                   2674:             const uschar *pp = start_subject + local_offsets[1];
                   2675:             while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;
                   2676:             ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
                   2677:             if (repeat_state_offset >= 0)
                   2678:               { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }
                   2679:             }
                   2680: 
                   2681:           }
                   2682:         else if (rc != PCRE_ERROR_NOMATCH) return rc;
                   2683:         }
                   2684:       break;
                   2685: 
                   2686: 
                   2687: /* ========================================================================== */
                   2688:       /* Handle callouts */
                   2689: 
                   2690:       case OP_CALLOUT:
1.3       misha    2691:       rrc = 0;
1.1       misha    2692:       if (pcre_callout != NULL)
                   2693:         {
                   2694:         pcre_callout_block cb;
                   2695:         cb.version          = 1;   /* Version 1 of the callout block */
                   2696:         cb.callout_number   = code[1];
                   2697:         cb.offset_vector    = offsets;
                   2698:         cb.subject          = (PCRE_SPTR)start_subject;
1.4     ! misha    2699:         cb.subject_length   = (int)(end_subject - start_subject);
        !          2700:         cb.start_match      = (int)(current_subject - start_subject);
        !          2701:         cb.current_position = (int)(ptr - start_subject);
1.1       misha    2702:         cb.pattern_position = GET(code, 2);
                   2703:         cb.next_item_length = GET(code, 2 + LINK_SIZE);
                   2704:         cb.capture_top      = 1;
                   2705:         cb.capture_last     = -1;
                   2706:         cb.callout_data     = md->callout_data;
                   2707:         if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc;   /* Abandon */
                   2708:         }
1.3       misha    2709:       if (rrc == 0)
                   2710:         { ADD_ACTIVE(state_offset + _pcre_OP_lengths[OP_CALLOUT], 0); }
1.1       misha    2711:       break;
                   2712: 
                   2713: 
                   2714: /* ========================================================================== */
                   2715:       default:        /* Unsupported opcode */
                   2716:       return PCRE_ERROR_DFA_UITEM;
                   2717:       }
                   2718: 
                   2719:     NEXT_ACTIVE_STATE: continue;
                   2720: 
                   2721:     }      /* End of loop scanning active states */
                   2722: 
                   2723:   /* We have finished the processing at the current subject character. If no
                   2724:   new states have been set for the next character, we have found all the
                   2725:   matches that we are going to find. If we are at the top level and partial
1.4     ! misha    2726:   matching has been requested, check for appropriate conditions.
        !          2727: 
        !          2728:   The "forced_ fail" variable counts the number of (*F) encountered for the
        !          2729:   character. If it is equal to the original active_count (saved in
        !          2730:   workspace[1]) it means that (*F) was found on every active state. In this
        !          2731:   case we don't want to give a partial match.
        !          2732: 
        !          2733:   The "could_continue" variable is true if a state could have continued but
        !          2734:   for the fact that the end of the subject was reached. */
1.1       misha    2735: 
                   2736:   if (new_count <= 0)
                   2737:     {
1.4     ! misha    2738:     if (rlevel == 1 &&                               /* Top level, and */
        !          2739:         could_continue &&                            /* Some could go on */
        !          2740:         forced_fail != workspace[1] &&               /* Not all forced fail & */
        !          2741:         (                                            /* either... */
        !          2742:         (md->moptions & PCRE_PARTIAL_HARD) != 0      /* Hard partial */
        !          2743:         ||                                           /* or... */
        !          2744:         ((md->moptions & PCRE_PARTIAL_SOFT) != 0 &&  /* Soft partial and */
        !          2745:          match_count < 0)                            /* no matches */
        !          2746:         ) &&                                         /* And... */
        !          2747:         ptr >= end_subject &&                     /* Reached end of subject */
        !          2748:         ptr > current_subject)                    /* Matched non-empty string */
1.1       misha    2749:       {
                   2750:       if (offsetcount >= 2)
                   2751:         {
1.4     ! misha    2752:         offsets[0] = (int)(md->start_used_ptr - start_subject);
        !          2753:         offsets[1] = (int)(end_subject - start_subject);
1.1       misha    2754:         }
                   2755:       match_count = PCRE_ERROR_PARTIAL;
                   2756:       }
                   2757: 
                   2758:     DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"
                   2759:       "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, match_count,
                   2760:       rlevel*2-2, SP));
                   2761:     break;        /* In effect, "return", but see the comment below */
                   2762:     }
                   2763: 
                   2764:   /* One or more states are active for the next character. */
                   2765: 
                   2766:   ptr += clen;    /* Advance to next subject character */
                   2767:   }               /* Loop to move along the subject string */
                   2768: 
                   2769: /* Control gets here from "break" a few lines above. We do it this way because
                   2770: if we use "return" above, we have compiler trouble. Some compilers warn if
                   2771: there's nothing here because they think the function doesn't return a value. On
                   2772: the other hand, if we put a dummy statement here, some more clever compilers
                   2773: complain that it can't be reached. Sigh. */
                   2774: 
                   2775: return match_count;
                   2776: }
                   2777: 
                   2778: 
                   2779: 
                   2780: 
                   2781: /*************************************************
                   2782: *    Execute a Regular Expression - DFA engine   *
                   2783: *************************************************/
                   2784: 
                   2785: /* This external function applies a compiled re to a subject string using a DFA
                   2786: engine. This function calls the internal function multiple times if the pattern
                   2787: is not anchored.
                   2788: 
                   2789: Arguments:
                   2790:   argument_re     points to the compiled expression
                   2791:   extra_data      points to extra data or is NULL
                   2792:   subject         points to the subject string
                   2793:   length          length of subject string (may contain binary zeros)
                   2794:   start_offset    where to start in the subject string
                   2795:   options         option bits
                   2796:   offsets         vector of match offsets
                   2797:   offsetcount     size of same
                   2798:   workspace       workspace vector
                   2799:   wscount         size of same
                   2800: 
                   2801: Returns:          > 0 => number of match offset pairs placed in offsets
                   2802:                   = 0 => offsets overflowed; longest matches are present
                   2803:                    -1 => failed to match
                   2804:                  < -1 => some kind of unexpected problem
                   2805: */
                   2806: 
1.2       misha    2807: PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
1.1       misha    2808: pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,
                   2809:   const char *subject, int length, int start_offset, int options, int *offsets,
                   2810:   int offsetcount, int *workspace, int wscount)
                   2811: {
                   2812: real_pcre *re = (real_pcre *)argument_re;
                   2813: dfa_match_data match_block;
                   2814: dfa_match_data *md = &match_block;
                   2815: BOOL utf8, anchored, startline, firstline;
                   2816: const uschar *current_subject, *end_subject, *lcc;
                   2817: 
                   2818: pcre_study_data internal_study;
                   2819: const pcre_study_data *study = NULL;
                   2820: real_pcre internal_re;
                   2821: 
                   2822: const uschar *req_byte_ptr;
                   2823: const uschar *start_bits = NULL;
                   2824: BOOL first_byte_caseless = FALSE;
                   2825: BOOL req_byte_caseless = FALSE;
                   2826: int first_byte = -1;
                   2827: int req_byte = -1;
                   2828: int req_byte2 = -1;
                   2829: int newline;
                   2830: 
                   2831: /* Plausibility checks */
                   2832: 
                   2833: if ((options & ~PUBLIC_DFA_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
                   2834: if (re == NULL || subject == NULL || workspace == NULL ||
                   2835:    (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
                   2836: if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
                   2837: if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE;
                   2838: 
                   2839: /* We need to find the pointer to any study data before we test for byte
                   2840: flipping, so we scan the extra_data block first. This may set two fields in the
                   2841: match block, so we must initialize them beforehand. However, the other fields
                   2842: in the match block must not be set until after the byte flipping. */
                   2843: 
                   2844: md->tables = re->tables;
                   2845: md->callout_data = NULL;
                   2846: 
                   2847: if (extra_data != NULL)
                   2848:   {
                   2849:   unsigned int flags = extra_data->flags;
                   2850:   if ((flags & PCRE_EXTRA_STUDY_DATA) != 0)
                   2851:     study = (const pcre_study_data *)extra_data->study_data;
                   2852:   if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) return PCRE_ERROR_DFA_UMLIMIT;
                   2853:   if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0)
                   2854:     return PCRE_ERROR_DFA_UMLIMIT;
                   2855:   if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0)
                   2856:     md->callout_data = extra_data->callout_data;
                   2857:   if ((flags & PCRE_EXTRA_TABLES) != 0)
                   2858:     md->tables = extra_data->tables;
                   2859:   }
                   2860: 
                   2861: /* Check that the first field in the block is the magic number. If it is not,
                   2862: test for a regex that was compiled on a host of opposite endianness. If this is
                   2863: the case, flipped values are put in internal_re and internal_study if there was
                   2864: study data too. */
                   2865: 
                   2866: if (re->magic_number != MAGIC_NUMBER)
                   2867:   {
                   2868:   re = _pcre_try_flipped(re, &internal_re, study, &internal_study);
                   2869:   if (re == NULL) return PCRE_ERROR_BADMAGIC;
                   2870:   if (study != NULL) study = &internal_study;
                   2871:   }
                   2872: 
                   2873: /* Set some local values */
                   2874: 
                   2875: current_subject = (const unsigned char *)subject + start_offset;
                   2876: end_subject = (const unsigned char *)subject + length;
                   2877: req_byte_ptr = current_subject - 1;
                   2878: 
                   2879: #ifdef SUPPORT_UTF8
                   2880: utf8 = (re->options & PCRE_UTF8) != 0;
                   2881: #else
                   2882: utf8 = FALSE;
                   2883: #endif
                   2884: 
                   2885: anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||
                   2886:   (re->options & PCRE_ANCHORED) != 0;
                   2887: 
                   2888: /* The remaining fixed data for passing around. */
                   2889: 
                   2890: md->start_code = (const uschar *)argument_re +
                   2891:     re->name_table_offset + re->name_count * re->name_entry_size;
                   2892: md->start_subject = (const unsigned char *)subject;
                   2893: md->end_subject = end_subject;
1.4     ! misha    2894: md->start_offset = start_offset;
1.1       misha    2895: md->moptions = options;
                   2896: md->poptions = re->options;
                   2897: 
                   2898: /* If the BSR option is not set at match time, copy what was set
                   2899: at compile time. */
                   2900: 
                   2901: if ((md->moptions & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == 0)
                   2902:   {
                   2903:   if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0)
                   2904:     md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE);
                   2905: #ifdef BSR_ANYCRLF
                   2906:   else md->moptions |= PCRE_BSR_ANYCRLF;
                   2907: #endif
                   2908:   }
                   2909: 
                   2910: /* Handle different types of newline. The three bits give eight cases. If
                   2911: nothing is set at run time, whatever was used at compile time applies. */
                   2912: 
                   2913: switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) &
                   2914:          PCRE_NEWLINE_BITS)
                   2915:   {
                   2916:   case 0: newline = NEWLINE; break;   /* Compile-time default */
1.3       misha    2917:   case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
                   2918:   case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
1.1       misha    2919:   case PCRE_NEWLINE_CR+
1.3       misha    2920:        PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
1.1       misha    2921:   case PCRE_NEWLINE_ANY: newline = -1; break;
                   2922:   case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
                   2923:   default: return PCRE_ERROR_BADNEWLINE;
                   2924:   }
                   2925: 
                   2926: if (newline == -2)
                   2927:   {
                   2928:   md->nltype = NLTYPE_ANYCRLF;
                   2929:   }
                   2930: else if (newline < 0)
                   2931:   {
                   2932:   md->nltype = NLTYPE_ANY;
                   2933:   }
                   2934: else
                   2935:   {
                   2936:   md->nltype = NLTYPE_FIXED;
                   2937:   if (newline > 255)
                   2938:     {
                   2939:     md->nllen = 2;
                   2940:     md->nl[0] = (newline >> 8) & 255;
                   2941:     md->nl[1] = newline & 255;
                   2942:     }
                   2943:   else
                   2944:     {
                   2945:     md->nllen = 1;
                   2946:     md->nl[0] = newline;
                   2947:     }
                   2948:   }
                   2949: 
                   2950: /* Check a UTF-8 string if required. Unfortunately there's no way of passing
                   2951: back the character offset. */
                   2952: 
                   2953: #ifdef SUPPORT_UTF8
                   2954: if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)
                   2955:   {
                   2956:   if (_pcre_valid_utf8((uschar *)subject, length) >= 0)
                   2957:     return PCRE_ERROR_BADUTF8;
                   2958:   if (start_offset > 0 && start_offset < length)
                   2959:     {
                   2960:     int tb = ((uschar *)subject)[start_offset];
                   2961:     if (tb > 127)
                   2962:       {
                   2963:       tb &= 0xc0;
                   2964:       if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET;
                   2965:       }
                   2966:     }
                   2967:   }
                   2968: #endif
                   2969: 
                   2970: /* If the exec call supplied NULL for tables, use the inbuilt ones. This
                   2971: is a feature that makes it possible to save compiled regex and re-use them
                   2972: in other programs later. */
                   2973: 
                   2974: if (md->tables == NULL) md->tables = _pcre_default_tables;
                   2975: 
                   2976: /* The lower casing table and the "must be at the start of a line" flag are
                   2977: used in a loop when finding where to start. */
                   2978: 
                   2979: lcc = md->tables + lcc_offset;
                   2980: startline = (re->flags & PCRE_STARTLINE) != 0;
                   2981: firstline = (re->options & PCRE_FIRSTLINE) != 0;
                   2982: 
                   2983: /* Set up the first character to match, if available. The first_byte value is
                   2984: never set for an anchored regular expression, but the anchoring may be forced
                   2985: at run time, so we have to test for anchoring. The first char may be unset for
                   2986: an unanchored pattern, of course. If there's no first char and the pattern was
                   2987: studied, there may be a bitmap of possible first characters. */
                   2988: 
                   2989: if (!anchored)
                   2990:   {
                   2991:   if ((re->flags & PCRE_FIRSTSET) != 0)
                   2992:     {
                   2993:     first_byte = re->first_byte & 255;
                   2994:     if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)
                   2995:       first_byte = lcc[first_byte];
                   2996:     }
                   2997:   else
                   2998:     {
1.4     ! misha    2999:     if (!startline && study != NULL &&
        !          3000:          (study->flags & PCRE_STUDY_MAPPED) != 0)
1.1       misha    3001:       start_bits = study->start_bits;
                   3002:     }
                   3003:   }
                   3004: 
                   3005: /* For anchored or unanchored matches, there may be a "last known required
                   3006: character" set. */
                   3007: 
                   3008: if ((re->flags & PCRE_REQCHSET) != 0)
                   3009:   {
                   3010:   req_byte = re->req_byte & 255;
                   3011:   req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;
                   3012:   req_byte2 = (md->tables + fcc_offset)[req_byte];  /* case flipped */
                   3013:   }
                   3014: 
                   3015: /* Call the main matching function, looping for a non-anchored regex after a
1.3       misha    3016: failed match. If not restarting, perform certain optimizations at the start of
                   3017: a match. */
1.1       misha    3018: 
                   3019: for (;;)
                   3020:   {
                   3021:   int rc;
                   3022: 
                   3023:   if ((options & PCRE_DFA_RESTART) == 0)
                   3024:     {
                   3025:     const uschar *save_end_subject = end_subject;
                   3026: 
1.3       misha    3027:     /* If firstline is TRUE, the start of the match is constrained to the first
                   3028:     line of a multiline string. Implement this by temporarily adjusting
                   3029:     end_subject so that we stop scanning at a newline. If the match fails at
                   3030:     the newline, later code breaks this loop. */
1.1       misha    3031: 
                   3032:     if (firstline)
                   3033:       {
1.2       misha    3034:       USPTR t = current_subject;
                   3035: #ifdef SUPPORT_UTF8
                   3036:       if (utf8)
                   3037:         {
                   3038:         while (t < md->end_subject && !IS_NEWLINE(t))
                   3039:           {
                   3040:           t++;
                   3041:           while (t < end_subject && (*t & 0xc0) == 0x80) t++;
                   3042:           }
                   3043:         }
                   3044:       else
                   3045: #endif
1.1       misha    3046:       while (t < md->end_subject && !IS_NEWLINE(t)) t++;
                   3047:       end_subject = t;
                   3048:       }
                   3049: 
1.3       misha    3050:     /* There are some optimizations that avoid running the match if a known
1.4     ! misha    3051:     starting point is not found. However, there is an option that disables
        !          3052:     these, for testing and for ensuring that all callouts do actually occur. */
1.3       misha    3053: 
                   3054:     if ((options & PCRE_NO_START_OPTIMIZE) == 0)
1.1       misha    3055:       {
1.3       misha    3056:       /* Advance to a known first byte. */
                   3057: 
                   3058:       if (first_byte >= 0)
                   3059:         {
                   3060:         if (first_byte_caseless)
                   3061:           while (current_subject < end_subject &&
                   3062:                  lcc[*current_subject] != first_byte)
                   3063:             current_subject++;
                   3064:         else
                   3065:           while (current_subject < end_subject &&
                   3066:                  *current_subject != first_byte)
                   3067:             current_subject++;
                   3068:         }
                   3069: 
                   3070:       /* Or to just after a linebreak for a multiline match if possible */
1.1       misha    3071: 
1.3       misha    3072:       else if (startline)
1.1       misha    3073:         {
1.3       misha    3074:         if (current_subject > md->start_subject + start_offset)
                   3075:           {
1.2       misha    3076: #ifdef SUPPORT_UTF8
1.3       misha    3077:           if (utf8)
1.2       misha    3078:             {
1.3       misha    3079:             while (current_subject < end_subject &&
                   3080:                    !WAS_NEWLINE(current_subject))
                   3081:               {
1.2       misha    3082:               current_subject++;
1.3       misha    3083:               while(current_subject < end_subject &&
                   3084:                     (*current_subject & 0xc0) == 0x80)
                   3085:                 current_subject++;
                   3086:               }
1.2       misha    3087:             }
1.3       misha    3088:           else
1.2       misha    3089: #endif
1.3       misha    3090:           while (current_subject < end_subject && !WAS_NEWLINE(current_subject))
                   3091:             current_subject++;
1.1       misha    3092: 
1.3       misha    3093:           /* If we have just passed a CR and the newline option is ANY or
                   3094:           ANYCRLF, and we are now at a LF, advance the match position by one
                   3095:           more character. */
                   3096: 
                   3097:           if (current_subject[-1] == CHAR_CR &&
                   3098:                (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
                   3099:                current_subject < end_subject &&
                   3100:                *current_subject == CHAR_NL)
                   3101:             current_subject++;
                   3102:           }
1.1       misha    3103:         }
                   3104: 
1.3       misha    3105:       /* Or to a non-unique first char after study */
1.1       misha    3106: 
1.3       misha    3107:       else if (start_bits != NULL)
1.1       misha    3108:         {
1.3       misha    3109:         while (current_subject < end_subject)
                   3110:           {
                   3111:           register unsigned int c = *current_subject;
1.4     ! misha    3112:           if ((start_bits[c/8] & (1 << (c&7))) == 0)
        !          3113:             {
        !          3114:             current_subject++;
        !          3115: #ifdef SUPPORT_UTF8
        !          3116:             if (utf8)
        !          3117:               while(current_subject < end_subject &&
        !          3118:                     (*current_subject & 0xc0) == 0x80) current_subject++;
        !          3119: #endif
        !          3120:             }
        !          3121:           else break;
1.3       misha    3122:           }
1.1       misha    3123:         }
                   3124:       }
                   3125: 
                   3126:     /* Restore fudged end_subject */
                   3127: 
                   3128:     end_subject = save_end_subject;
                   3129: 
1.4     ! misha    3130:     /* The following two optimizations are disabled for partial matching or if
        !          3131:     disabling is explicitly requested (and of course, by the test above, this
        !          3132:     code is not obeyed when restarting after a partial match). */
        !          3133: 
        !          3134:     if ((options & PCRE_NO_START_OPTIMIZE) == 0 &&
        !          3135:         (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0)
        !          3136:       {
        !          3137:       /* If the pattern was studied, a minimum subject length may be set. This
        !          3138:       is a lower bound; no actual string of that length may actually match the
        !          3139:       pattern. Although the value is, strictly, in characters, we treat it as
        !          3140:       bytes to avoid spending too much time in this optimization. */
        !          3141: 
        !          3142:       if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 &&
        !          3143:           (pcre_uint32)(end_subject - current_subject) < study->minlength)
        !          3144:         return PCRE_ERROR_NOMATCH;
        !          3145: 
        !          3146:       /* If req_byte is set, we know that that character must appear in the
        !          3147:       subject for the match to succeed. If the first character is set, req_byte
        !          3148:       must be later in the subject; otherwise the test starts at the match
        !          3149:       point. This optimization can save a huge amount of work in patterns with
        !          3150:       nested unlimited repeats that aren't going to match. Writing separate
        !          3151:       code for cased/caseless versions makes it go faster, as does using an
        !          3152:       autoincrement and backing off on a match.
1.1       misha    3153: 
1.4     ! misha    3154:       HOWEVER: when the subject string is very, very long, searching to its end
        !          3155:       can take a long time, and give bad performance on quite ordinary
        !          3156:       patterns. This showed up when somebody was matching /^C/ on a 32-megabyte
        !          3157:       string... so we don't do this when the string is sufficiently long. */
1.1       misha    3158: 
1.4     ! misha    3159:       if (req_byte >= 0 && end_subject - current_subject < REQ_BYTE_MAX)
1.1       misha    3160:         {
1.4     ! misha    3161:         register const uschar *p = current_subject + ((first_byte >= 0)? 1 : 0);
        !          3162: 
        !          3163:         /* We don't need to repeat the search if we haven't yet reached the
        !          3164:         place we found it at last time. */
        !          3165: 
        !          3166:         if (p > req_byte_ptr)
1.1       misha    3167:           {
1.4     ! misha    3168:           if (req_byte_caseless)
        !          3169:             {
        !          3170:             while (p < end_subject)
        !          3171:               {
        !          3172:               register int pp = *p++;
        !          3173:               if (pp == req_byte || pp == req_byte2) { p--; break; }
        !          3174:               }
        !          3175:             }
        !          3176:           else
        !          3177:             {
        !          3178:             while (p < end_subject)
        !          3179:               {
        !          3180:               if (*p++ == req_byte) { p--; break; }
        !          3181:               }
        !          3182:             }
1.1       misha    3183: 
1.4     ! misha    3184:           /* If we can't find the required character, break the matching loop,
        !          3185:           which will cause a return or PCRE_ERROR_NOMATCH. */
1.1       misha    3186: 
1.4     ! misha    3187:           if (p >= end_subject) break;
1.1       misha    3188: 
1.4     ! misha    3189:           /* If we have found the required character, save the point where we
        !          3190:           found it, so that we don't search again next time round the loop if
        !          3191:           the start hasn't passed this character yet. */
1.1       misha    3192: 
1.4     ! misha    3193:           req_byte_ptr = p;
        !          3194:           }
        !          3195:         }
1.1       misha    3196:       }
1.4     ! misha    3197:     }   /* End of optimizations that are done when not restarting */
1.1       misha    3198: 
                   3199:   /* OK, now we can do the business */
                   3200: 
1.4     ! misha    3201:   md->start_used_ptr = current_subject;
        !          3202: 
1.1       misha    3203:   rc = internal_dfa_exec(
                   3204:     md,                                /* fixed match data */
                   3205:     md->start_code,                    /* this subexpression's code */
                   3206:     current_subject,                   /* where we currently are */
                   3207:     start_offset,                      /* start offset in subject */
                   3208:     offsets,                           /* offset vector */
                   3209:     offsetcount,                       /* size of same */
                   3210:     workspace,                         /* workspace vector */
                   3211:     wscount,                           /* size of same */
                   3212:     re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL), /* ims flags */
                   3213:     0,                                 /* function recurse level */
                   3214:     0);                                /* regex recurse level */
                   3215: 
                   3216:   /* Anything other than "no match" means we are done, always; otherwise, carry
                   3217:   on only if not anchored. */
                   3218: 
                   3219:   if (rc != PCRE_ERROR_NOMATCH || anchored) return rc;
                   3220: 
                   3221:   /* Advance to the next subject character unless we are at the end of a line
                   3222:   and firstline is set. */
                   3223: 
                   3224:   if (firstline && IS_NEWLINE(current_subject)) break;
                   3225:   current_subject++;
                   3226:   if (utf8)
                   3227:     {
                   3228:     while (current_subject < end_subject && (*current_subject & 0xc0) == 0x80)
                   3229:       current_subject++;
                   3230:     }
                   3231:   if (current_subject > end_subject) break;
                   3232: 
                   3233:   /* If we have just passed a CR and we are now at a LF, and the pattern does
                   3234:   not contain any explicit matches for \r or \n, and the newline option is CRLF
                   3235:   or ANY or ANYCRLF, advance the match position by one more character. */
                   3236: 
1.3       misha    3237:   if (current_subject[-1] == CHAR_CR &&
1.1       misha    3238:       current_subject < end_subject &&
1.3       misha    3239:       *current_subject == CHAR_NL &&
1.1       misha    3240:       (re->flags & PCRE_HASCRORLF) == 0 &&
                   3241:         (md->nltype == NLTYPE_ANY ||
                   3242:          md->nltype == NLTYPE_ANYCRLF ||
                   3243:          md->nllen == 2))
                   3244:     current_subject++;
                   3245: 
                   3246:   }   /* "Bumpalong" loop */
                   3247: 
                   3248: return PCRE_ERROR_NOMATCH;
                   3249: }
                   3250: 
                   3251: /* End of pcre_dfa_exec.c */

E-mail: