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

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

E-mail: