[Pcre-svn] [602] code/trunk: Remove OP_OPT by handling /i an…

Página Inicial
Delete this message
Autor: Subversion repository
Data:  
Para: pcre-svn
Assunto: [Pcre-svn] [602] code/trunk: Remove OP_OPT by handling /i and / m entirely at compile time.
Revision: 602
          http://vcs.pcre.org/viewvc?view=rev&revision=602
Author:   ph10
Date:     2011-05-25 09:29:03 +0100 (Wed, 25 May 2011)


Log Message:
-----------
Remove OP_OPT by handling /i and /m entirely at compile time. Fixes bug with
patterns like /(?i:([^b]))(?1)/, where the /i option was mishandled.

Modified Paths:
--------------
    code/trunk/ChangeLog
    code/trunk/HACKING
    code/trunk/pcre_compile.c
    code/trunk/pcre_dfa_exec.c
    code/trunk/pcre_exec.c
    code/trunk/pcre_internal.h
    code/trunk/pcre_printint.src
    code/trunk/pcre_study.c
    code/trunk/testdata/testinput1
    code/trunk/testdata/testinput11
    code/trunk/testdata/testinput2
    code/trunk/testdata/testoutput1
    code/trunk/testdata/testoutput10
    code/trunk/testdata/testoutput11
    code/trunk/testdata/testoutput12
    code/trunk/testdata/testoutput2


Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/ChangeLog    2011-05-25 08:29:03 UTC (rev 602)
@@ -43,6 +43,15 @@
     documentation that \R is equivalent to (?>\r\n|\n|...etc), and makes the
     behaviour of \R* different to (\R)*, which also seems wrong. The behaviour 
     has been changed.
+    
+9.  Some internal refactoring has changed the processing so that the handling 
+    of the PCRE_CASELESS and PCRE_MULTILINE options is done entirely at compile
+    time (the PCRE_DOTALL option was changed this way some time ago: version
+    7.7 change 16). This has made it possible to abolish the OP_OPT op code, 
+    which was always a bit of a fudge. It also means that there is one less 
+    argument for the match() function, which reduces its stack requirements 
+    slightly. This change also fixes an incompatibility with Perl: the pattern
+    (?i:([^b]))(?1) should not match "ab", but previously PCRE gave a match.



Version 8.12 15-Jan-2011

Modified: code/trunk/HACKING
===================================================================
--- code/trunk/HACKING    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/HACKING    2011-05-25 08:29:03 UTC (rev 602)
@@ -68,7 +68,7 @@
 I had a flash of inspiration as to how I could run the real compile function in
 a "fake" mode that enables it to compute how much memory it would need, while
 actually only ever using a few hundred bytes of working memory, and without too
-many tests of the mode that might slow it down. So I re-factored the compiling
+many tests of the mode that might slow it down. So I refactored the compiling
 functions to work this way. This got rid of about 600 lines of source. It
 should make future maintenance and development easier. As this was such a major 
 change, I never released 6.8, instead upping the number to 7.0 (other quite 
@@ -108,6 +108,16 @@
 ever active at once. I believe some other regex matchers work this way.



+Changeable options
+------------------
+
+The /i, /m, or /s options (PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL) may
+change in the middle of patterns. From PCRE 8.13, their processing is handled
+entirely at compile time by generating different opcodes for the different
+settings. The runtime functions do not need to keep track of an options state
+any more.
+
+
Format of compiled patterns
---------------------------

@@ -124,8 +134,6 @@
"normal" compilation options. Data values that are counts (e.g. for
quantifiers) are always just two bytes long.

-A list of the opcodes follows:
-
Opcodes with no following data
------------------------------

@@ -138,7 +146,8 @@
   OP_SOD                 match start of data: \A
   OP_SOM,                start of match (subject + offset): \G
   OP_SET_SOM,            set start of match (\K) 
-  OP_CIRC                ^ (start of data, or after \n in multiline)
+  OP_CIRC                ^ (start of data)
+  OP_CIRCM               ^ multiline mode (start of data or after newline)
   OP_NOT_WORD_BOUNDARY   \W
   OP_WORD_BOUNDARY       \w
   OP_NOT_DIGIT           \D
@@ -153,7 +162,8 @@
   OP_WORDCHAR            \w
   OP_EODN                match end of data or \n at end: \Z
   OP_EOD                 match end of data: \z
-  OP_DOLL                $ (end of data, or before \n in multiline)
+  OP_DOLL                $ (end of data, or before final newline)
+  OP_DOLLM               $ multiline mode (end of data or before newline)
   OP_EXTUNI              match an extended Unicode character 
   OP_ANYNL               match any Unicode newline sequence 


@@ -177,33 +187,45 @@
offset value.


+Matching literal characters
+---------------------------
+
+The OP_CHAR opcode is followed by a single character that is to be matched
+casefully. For caseless matching, OP_CHARI is used. In UTF-8 mode, the
+character may be more than one byte long. (Earlier versions of PCRE used
+multi-character strings, but this was changed to allow some new features to be
+added.)
+
+
Repeating single characters
---------------------------

The common repeats (*, +, ?) when applied to a single character use the
-following opcodes:
+following opcodes, which come in caseful and caseless versions:

-  OP_STAR
-  OP_MINSTAR
-  OP_POSSTAR 
-  OP_PLUS
-  OP_MINPLUS
-  OP_POSPLUS 
-  OP_QUERY
-  OP_MINQUERY
-  OP_POSQUERY 
+  Caseful         Caseless
+  OP_STAR         OP_STARI      
+  OP_MINSTAR      OP_MINSTARI   
+  OP_POSSTAR      OP_POSSTARI   
+  OP_PLUS         OP_PLUSI      
+  OP_MINPLUS      OP_MINPLUSI   
+  OP_POSPLUS      OP_POSPLUSI   
+  OP_QUERY        OP_QUERYI     
+  OP_MINQUERY     OP_MINQUERYI  
+  OP_POSQUERY     OP_POSQUERYI  


In ASCII mode, these are two-byte items; in UTF-8 mode, the length is variable.
Those with "MIN" in their name are the minimizing versions. Those with "POS" in
their names are possessive versions. Each is followed by the character that is
-to be repeated. Other repeats make use of
+to be repeated. Other repeats make use of these opcodes:

-  OP_UPTO
-  OP_MINUPTO
-  OP_POSUPTO 
-  OP_EXACT
+  Caseful         Caseless
+  OP_UPTO         OP_UPTOI    
+  OP_MINUPTO      OP_MINUPTOI 
+  OP_POSUPTO      OP_POSUPTOI 
+  OP_EXACT        OP_EXACTI   


-which are followed by a two-byte count (most significant first) and the
+Each of these is followed by a two-byte count (most significant first) and the
repeated character. OP_UPTO matches from 0 to the given number. A repeat with a
non-zero minimum and a fixed maximum is coded as an OP_EXACT followed by an
OP_UPTO (or OP_MINUPTO or OPT_POSUPTO).
@@ -244,57 +266,50 @@
value.


-Matching literal characters
----------------------------
-
-The OP_CHAR opcode is followed by a single character that is to be matched
-casefully. For caseless matching, OP_CHARNC is used. In UTF-8 mode, the
-character may be more than one byte long. (Earlier versions of PCRE used
-multi-character strings, but this was changed to allow some new features to be
-added.)
-
-
Character classes
-----------------

-If there is only one character, OP_CHAR or OP_CHARNC is used for a positive
-class, and OP_NOT for a negative one (that is, for something like [^a]).
-However, in UTF-8 mode, the use of OP_NOT applies only to characters with
-values < 128, because OP_NOT is confined to single bytes.
+If there is only one character, OP_CHAR or OP_CHARI is used for a positive
+class, and OP_NOT or OP_NOTI for a negative one (that is, for something like
+[^a]). However, in UTF-8 mode, the use of OP_NOT[I] applies only to characters
+with values < 128, because OP_NOT[I] is confined to single bytes.

-Another set of repeating opcodes (OP_NOTSTAR etc.) are used for a repeated,
-negated, single-character class. The normal ones (OP_STAR etc.) are used for a
-repeated positive single-character class.
+Another set of 13 repeating opcodes (called OP_NOTSTAR etc.) are used for a
+repeated, negated, single-character class. The normal single-character opcodes
+(OP_STAR, etc.) are used for a repeated positive single-character class.

-When there's more than one character in a class and all the characters are less
-than 256, OP_CLASS is used for a positive class, and OP_NCLASS for a negative
-one. In either case, the opcode is followed by a 32-byte bit map containing a 1
-bit for every character that is acceptable. The bits are counted from the least
-significant end of each byte.
+When there is more than one character in a class and all the characters are
+less than 256, OP_CLASS is used for a positive class, and OP_NCLASS for a
+negative one. In either case, the opcode is followed by a 32-byte bit map
+containing a 1 bit for every character that is acceptable. The bits are counted
+from the least significant end of each byte. In caseless mode, bits for both
+cases are set.

The reason for having both OP_CLASS and OP_NCLASS is so that, in UTF-8 mode,
subject characters with values greater than 256 can be handled correctly. For
-OP_CLASS they don't match, whereas for OP_NCLASS they do.
+OP_CLASS they do not match, whereas for OP_NCLASS they do.

For classes containing characters with values > 255, OP_XCLASS is used. It
optionally uses a bit map (if any characters lie within it), followed by a list
-of pairs and single characters. There is a flag character than indicates
-whether it's a positive or a negative class.
+of pairs (for a range) and single characters. In caseless mode, both cases are
+explicitly listed. There is a flag character than indicates whether it is a
+positive or a negative class.


Back references
---------------

-OP_REF is followed by two bytes containing the reference number.
+OP_REF (caseful) or OP_REFI (caseless) is followed by two bytes containing the
+reference number.


Repeating character classes and back references
-----------------------------------------------

Single-character classes are handled specially (see above). This section
-applies to OP_CLASS and OP_REF. In both cases, the repeat information follows
-the base item. The matching code looks at the following opcode to see if it is
-one of
+applies to OP_CLASS and OP_REF[I]. In both cases, the repeat information
+follows the base item. The matching code looks at the following opcode to see
+if it is one of

OP_CRSTAR
OP_CRMINSTAR
@@ -423,18 +438,5 @@
next item.


-Changing options
-----------------
-
-If any of the /i, /m, or /s options are changed within a pattern, an OP_OPT
-opcode is compiled, followed by one byte containing the new settings of these
-flags. If there are several alternatives, there is an occurrence of OP_OPT at
-the start of all those following the first options change, to set appropriate
-options for the start of the alternative. Immediately after the end of the
-group there is another such item to reset the flags to their previous values. A
-change of flag right at the very start of the pattern can be handled entirely
-at compile time, and so does not cause anything to be put into the compiled
-data.
-
Philip Hazel
-October 2010
+May 2011

Modified: code/trunk/pcre_compile.c
===================================================================
--- code/trunk/pcre_compile.c    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/pcre_compile.c    2011-05-25 08:29:03 UTC (rev 602)
@@ -1397,9 +1397,9 @@


/* This is called by several functions that scan a compiled expression looking
for a fixed first character, or an anchoring op code etc. It skips over things
-that do not influence this. For some calls, a change of option is important.
-For some calls, it makes sense to skip negative forward and all backward
-assertions, and also the \b assertion; for others it does not.
+that do not influence this. For some calls, it makes sense to skip negative
+forward and all backward assertions, and also the \b assertion; for others it
+does not.

 Arguments:
   code         pointer to the start of the group
@@ -1419,12 +1419,6 @@
   {
   switch ((int)*code)
     {
-    case OP_OPT:
-    if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit))
-      *options = (int)code[1];
-    code += 2;
-    break;
-
     case OP_ASSERT_NOT:
     case OP_ASSERTBACK:
     case OP_ASSERTBACK_NOT:
@@ -1561,7 +1555,6 @@
     case OP_RREF:
     case OP_NRREF:
     case OP_DEF:
-    case OP_OPT:
     case OP_CALLOUT:
     case OP_SOD:
     case OP_SOM:
@@ -1569,7 +1562,9 @@
     case OP_EOD:
     case OP_EODN:
     case OP_CIRC:
+    case OP_CIRCM:
     case OP_DOLL:
+    case OP_DOLLM:
     case OP_NOT_WORD_BOUNDARY:
     case OP_WORD_BOUNDARY:
     cc += _pcre_OP_lengths[*cc];
@@ -1578,8 +1573,9 @@
     /* Handle literal characters */


     case OP_CHAR:
-    case OP_CHARNC:
+    case OP_CHARI:
     case OP_NOT:
+    case OP_NOTI: 
     branchlength++;
     cc += 2;
 #ifdef SUPPORT_UTF8
@@ -1774,20 +1770,33 @@
     if (utf8) switch(c)
       {
       case OP_CHAR:
-      case OP_CHARNC:
+      case OP_CHARI:
       case OP_EXACT:
+      case OP_EXACTI:
       case OP_UPTO:
+      case OP_UPTOI:
       case OP_MINUPTO:
+      case OP_MINUPTOI:
       case OP_POSUPTO:
+      case OP_POSUPTOI:
       case OP_STAR:
+      case OP_STARI:
       case OP_MINSTAR:
+      case OP_MINSTARI:
       case OP_POSSTAR:
+      case OP_POSSTARI:
       case OP_PLUS:
+      case OP_PLUSI:
       case OP_MINPLUS:
+      case OP_MINPLUSI:
       case OP_POSPLUS:
+      case OP_POSPLUSI:
       case OP_QUERY:
+      case OP_QUERYI:
       case OP_MINQUERY:
+      case OP_MINQUERYI:
       case OP_POSQUERY:
+      case OP_POSQUERYI:
       if (code[-1] >= 0xc0) code += _pcre_utf8_table4[code[-1] & 0x3f];
       break;
       }
@@ -1880,20 +1889,33 @@
     if (utf8) switch(c)
       {
       case OP_CHAR:
-      case OP_CHARNC:
+      case OP_CHARI:
       case OP_EXACT:
+      case OP_EXACTI:
       case OP_UPTO:
+      case OP_UPTOI:
       case OP_MINUPTO:
+      case OP_MINUPTOI:
       case OP_POSUPTO:
+      case OP_POSUPTOI:
       case OP_STAR:
+      case OP_STARI:
       case OP_MINSTAR:
+      case OP_MINSTARI:
       case OP_POSSTAR:
+      case OP_POSSTARI:
       case OP_PLUS:
+      case OP_PLUSI:
       case OP_MINPLUS:
+      case OP_MINPLUSI:
       case OP_POSPLUS:
+      case OP_POSPLUSI:
       case OP_QUERY:
+      case OP_QUERYI:
       case OP_MINQUERY:
+      case OP_MINQUERYI:
       case OP_POSQUERY:
+      case OP_POSQUERYI:
       if (code[-1] >= 0xc0) code += _pcre_utf8_table4[code[-1] & 0x3f];
       break;
       }
@@ -2071,8 +2093,9 @@
     case OP_ALLANY:
     case OP_ANYBYTE:
     case OP_CHAR:
-    case OP_CHARNC:
+    case OP_CHARI:
     case OP_NOT:
+    case OP_NOTI:
     case OP_PLUS:
     case OP_MINPLUS:
     case OP_POSPLUS:
@@ -2120,17 +2143,26 @@


 #ifdef SUPPORT_UTF8
     case OP_STAR:
+    case OP_STARI:
     case OP_MINSTAR:
+    case OP_MINSTARI:
     case OP_POSSTAR:
+    case OP_POSSTARI:
     case OP_QUERY:
+    case OP_QUERYI:
     case OP_MINQUERY:
+    case OP_MINQUERYI:
     case OP_POSQUERY:
+    case OP_POSQUERYI:
     if (utf8 && code[1] >= 0xc0) code += _pcre_utf8_table4[code[1] & 0x3f];
     break;


     case OP_UPTO:
+    case OP_UPTOI:
     case OP_MINUPTO:
+    case OP_MINUPTOI:
     case OP_POSUPTO:
+    case OP_POSUPTOI:
     if (utf8 && code[3] >= 0xc0) code += _pcre_utf8_table4[code[3] & 0x3f];
     break;
 #endif
@@ -2622,11 +2654,11 @@
 #endif
   return c != next;


- /* For CHARNC (caseless character) we must check the other case. If we have
+ /* For CHARI (caseless character) we must check the other case. If we have
Unicode property support, we can use it to test the other case of
high-valued characters. */

- case OP_CHARNC:
+ case OP_CHARI:
#ifdef SUPPORT_UTF8
GETCHARTEST(c, previous);
#else
@@ -2649,11 +2681,15 @@
#endif /* SUPPORT_UTF8 */
return (c != cd->fcc[next]); /* Non-UTF-8 mode */

- /* For OP_NOT, its data is always a single-byte character. */
+ /* For OP_NOT and OP_NOTI, the data is always a single-byte character. These
+ opcodes are not used for multi-byte characters, because they are coded using
+ an XCLASS instead. */

   case OP_NOT:
+  return (c = *previous) == next;
+ 
+  case OP_NOTI: 
   if ((c = *previous) == next) return TRUE;
-  if ((options & PCRE_CASELESS) == 0) return FALSE;
 #ifdef SUPPORT_UTF8
   if (utf8)
     {
@@ -2758,7 +2794,7 @@
 switch(op_code)
   {
   case OP_CHAR:
-  case OP_CHARNC:
+  case OP_CHARI:
 #ifdef SUPPORT_UTF8
   GETCHARTEST(c, previous);
 #else
@@ -3222,17 +3258,18 @@
     the setting of any following char as a first character. */


     case CHAR_CIRCUMFLEX_ACCENT:
+    previous = NULL;
     if ((options & PCRE_MULTILINE) != 0)
       {
       if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
+      *code++ = OP_CIRCM;
       }
-    previous = NULL;
-    *code++ = OP_CIRC;
+    else *code++ = OP_CIRC;
     break;


     case CHAR_DOLLAR_SIGN:
     previous = NULL;
-    *code++ = OP_DOLL;
+    *code++ = ((options & PCRE_MULTILINE) != 0)? OP_DOLLM : OP_DOLL;
     break;


     /* There can never be a first char if '.' is first, whatever happens about
@@ -3978,15 +4015,15 @@


     In UTF-8 mode, we can optimize the negative case only if there were no
     characters >= 128 because OP_NOT and the related opcodes like OP_NOTSTAR
-    operate on single-bytes only. This is an historical hangover. Maybe one day
-    we can tidy these opcodes to handle multi-byte characters.
+    operate on single-bytes characters only. This is an historical hangover.
+    Maybe one day we can tidy these opcodes to handle multi-byte characters.


     The optimization throws away the bit map. We turn the item into a
-    1-character OP_CHAR[NC] if it's positive, or OP_NOT if it's negative. Note
-    that OP_NOT does not support multibyte characters. In the positive case, it
-    can cause firstbyte to be set. Otherwise, there can be no first char if
-    this item is first, whatever repeat count may follow. In the case of
-    reqbyte, save the previous value for reinstating. */
+    1-character OP_CHAR[I] if it's positive, or OP_NOT[I] if it's negative.
+    Note that OP_NOT[I] does not support multibyte characters. In the positive
+    case, it can cause firstbyte to be set. Otherwise, there can be no first
+    char if this item is first, whatever repeat count may follow. In the case
+    of reqbyte, save the previous value for reinstating. */


 #ifdef SUPPORT_UTF8
     if (class_charcount == 1 && !class_utf8 &&
@@ -3997,13 +4034,13 @@
       {
       zeroreqbyte = reqbyte;


-      /* The OP_NOT opcode works on one-byte characters only. */
+      /* The OP_NOT[I] opcodes work on one-byte characters only. */


       if (negate_class)
         {
         if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
         zerofirstbyte = firstbyte;
-        *code++ = OP_NOT;
+        *code++ = ((options & PCRE_CASELESS) != 0)? OP_NOTI: OP_NOT;
         *code++ = class_lastchar;
         break;
         }
@@ -4161,8 +4198,10 @@
     the first thing in a branch because the x will have gone into firstbyte
     instead.  */


-    if (*previous == OP_CHAR || *previous == OP_CHARNC)
+    if (*previous == OP_CHAR || *previous == OP_CHARI)
       {
+      op_type = (*previous == OP_CHAR)? 0 : OP_STARI - OP_STAR;
+        
       /* Deal with UTF-8 characters that take up more than one byte. It's
       easier to write this out separately than try to macrify it. Use c to
       hold the length of the character in bytes, plus 0x80 to flag that it's a
@@ -4207,12 +4246,12 @@
     /* If previous was a single negated character ([^a] or similar), we use
     one of the special opcodes, replacing it. The code is shared with single-
     character repeats by setting opt_type to add a suitable offset into
-    repeat_type. We can also test for auto-possessification. OP_NOT is
-    currently used only for single-byte chars. */
+    repeat_type. We can also test for auto-possessification. OP_NOT and OP_NOTI 
+    are currently used only for single-byte chars. */


-    else if (*previous == OP_NOT)
+    else if (*previous == OP_NOT || *previous == OP_NOTI)
       {
-      op_type = OP_NOTSTAR - OP_STAR;  /* Use "not" opcodes */
+      op_type = ((*previous == OP_NOT)? OP_NOTSTAR : OP_NOTSTARI) - OP_STAR;
       c = previous[1];
       if (!possessive_quantifier &&
           repeat_max < 0 &&
@@ -4409,7 +4448,8 @@
 #ifdef SUPPORT_UTF8
              *previous == OP_XCLASS ||
 #endif
-             *previous == OP_REF)
+             *previous == OP_REF ||
+             *previous == OP_REFI)
       {
       if (repeat_max == 0)
         {
@@ -4463,9 +4503,7 @@


       /* If the maximum repeat count is unlimited, find the end of the bracket
       by scanning through from the start, and compute the offset back to it
-      from the current code pointer. There may be an OP_OPT setting following
-      the final KET, so we can't find the end just by going back from the code
-      pointer. */
+      from the current code pointer. */


       if (repeat_max == -1)
         {
@@ -4765,16 +4803,26 @@
         case OP_QUERY: *tempcode = OP_POSQUERY; break;
         case OP_UPTO:  *tempcode = OP_POSUPTO; break;


-        case OP_TYPESTAR:  *tempcode = OP_TYPEPOSSTAR; break;
-        case OP_TYPEPLUS:  *tempcode = OP_TYPEPOSPLUS; break;
-        case OP_TYPEQUERY: *tempcode = OP_TYPEPOSQUERY; break;
-        case OP_TYPEUPTO:  *tempcode = OP_TYPEPOSUPTO; break;
+        case OP_STARI:  *tempcode = OP_POSSTARI; break;
+        case OP_PLUSI:  *tempcode = OP_POSPLUSI; break;
+        case OP_QUERYI: *tempcode = OP_POSQUERYI; break;
+        case OP_UPTOI:  *tempcode = OP_POSUPTOI; break;


         case OP_NOTSTAR:  *tempcode = OP_NOTPOSSTAR; break;
         case OP_NOTPLUS:  *tempcode = OP_NOTPOSPLUS; break;
         case OP_NOTQUERY: *tempcode = OP_NOTPOSQUERY; break;
         case OP_NOTUPTO:  *tempcode = OP_NOTPOSUPTO; break;


+        case OP_NOTSTARI:  *tempcode = OP_NOTPOSSTARI; break;
+        case OP_NOTPLUSI:  *tempcode = OP_NOTPOSPLUSI; break;
+        case OP_NOTQUERYI: *tempcode = OP_NOTPOSQUERYI; break;
+        case OP_NOTUPTOI:  *tempcode = OP_NOTPOSUPTOI; break;
+
+        case OP_TYPESTAR:  *tempcode = OP_TYPEPOSSTAR; break;
+        case OP_TYPEPLUS:  *tempcode = OP_TYPEPOSPLUS; break;
+        case OP_TYPEQUERY: *tempcode = OP_TYPEPOSQUERY; break;
+        case OP_TYPEUPTO:  *tempcode = OP_TYPEPOSUPTO; break;
+
         /* Because we are moving code along, we must ensure that any
         pending recursive references are updated. */


@@ -5679,11 +5727,6 @@
             }
           else
             {
-            if ((options & PCRE_IMS) != (newoptions & PCRE_IMS))
-              {
-              *code++ = OP_OPT;
-              *code++ = newoptions & PCRE_IMS;
-              }
             greedy_default = ((newoptions & PCRE_UNGREEDY) != 0);
             greedy_non_default = greedy_default ^ 1;
             req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS : 0;
@@ -6021,7 +6064,7 @@
         HANDLE_REFERENCE:    /* Come here from named backref handling */
         if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
         previous = code;
-        *code++ = OP_REF;
+        *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF;
         PUT2INC(code, 0, recno);
         cd->backref_map |= (recno < 32)? (1 << recno) : 1;
         if (recno > cd->top_backref) cd->top_backref = recno;
@@ -6129,7 +6172,7 @@


     ONE_CHAR:
     previous = code;
-    *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARNC : OP_CHAR;
+    *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARI : OP_CHAR;
     for (c = 0; c < mclength; c++) *code++ = mcbuffer[c];


     /* Remember if \r or \n were seen */
@@ -6193,11 +6236,6 @@
 /* On entry, ptr is pointing past the bracket character, but on return it
 points to the closing bracket, or vertical bar, or end of string. The code
 variable is pointing at the byte into which the BRA operator has been stored.
-If the ims options are changed at the start (for a (?ims: group) or during any
-branch, we need to insert an OP_OPT item at the start of every following branch
-to ensure they get set correctly at run time, and also pass the new options
-into every subsequent branch compile.
-
 This function is used during the pre-compile phase when we are trying to find
 out the amount of memory needed, as well as during the real compile phase. The
 value of lengthptr distinguishes the two phases.
@@ -6289,15 +6327,6 @@


if (reset_bracount) cd->bracount = orig_bracount;

-  /* Handle a change of ims options at the start of the branch */
-
-  if ((options & PCRE_IMS) != oldims)
-    {
-    *code++ = OP_OPT;
-    *code++ = options & PCRE_IMS;
-    length += 2;
-    }
-
   /* Set up dummy OP_REVERSE if lookbehind assertion */


   if (lookbehind)
@@ -6454,15 +6483,6 @@
       cd->open_caps = cd->open_caps->next;
       }


-    /* Reset options if needed. */
-
-    if ((options & PCRE_IMS) != oldims && *ptr == CHAR_RIGHT_PARENTHESIS)
-      {
-      *code++ = OP_OPT;
-      *code++ = oldims;
-      length += 2;
-      }
-
     /* Retain the highest bracket number, in case resetting was used. */


     cd->bracount = max_bracount;
@@ -6522,8 +6542,8 @@
 /* Try to find out if this is an anchored regular expression. Consider each
 alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket
 all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then
-it's anchored. However, if this is a multiline pattern, then only OP_SOD
-counts, since OP_CIRC can match in the middle.
+it's anchored. However, if this is a multiline pattern, then only OP_SOD will
+be found, because ^ generates OP_CIRCM in that mode.


We can also consider a regex to be anchored if OP_SOM starts all its branches.
This is the code for \G, which means "match at start of match position, taking
@@ -6597,9 +6617,7 @@

    /* Check for explicit anchoring */


-   else if (op != OP_SOD && op != OP_SOM &&
-           ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC))
-     return FALSE;
+   else if (op != OP_SOD && op != OP_SOM && op != OP_CIRC) return FALSE;
    code += GET(code, 1);
    }
 while (*code == OP_ALT);   /* Loop for each alternative */
@@ -6699,7 +6717,7 @@


    /* Check for explicit circumflex */


- else if (op != OP_CIRC) return FALSE;
+ else if (op != OP_CIRC && op != OP_CIRCM) return FALSE;

    /* Move on to the next alternative */


@@ -6760,7 +6778,7 @@
      scode += 2;


      case OP_CHAR:
-     case OP_CHARNC:
+     case OP_CHARI:
      case OP_PLUS:
      case OP_MINPLUS:
      case OP_POSPLUS:


Modified: code/trunk/pcre_dfa_exec.c
===================================================================
--- code/trunk/pcre_dfa_exec.c    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/pcre_dfa_exec.c    2011-05-25 08:29:03 UTC (rev 602)
@@ -121,18 +121,25 @@
   0, 0,                          /* \P, \p                                 */
   0, 0, 0, 0, 0,                 /* \R, \H, \h, \V, \v                     */
   0,                             /* \X                                     */
-  0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, $                      */
+  0, 0, 0, 0, 0, 0,              /* \Z, \z, ^, ^M, $, $M                   */
   1,                             /* Char                                   */
-  1,                             /* Charnc                                 */
+  1,                             /* Chari                                  */
   1,                             /* not                                    */
+  1,                             /* noti                                   */
   /* Positive single-char repeats                                          */
   1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
   3, 3, 3,                       /* upto, minupto, exact                   */
   1, 1, 1, 3,                    /* *+, ++, ?+, upto+                      */
+  1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */
+  3, 3, 3,                       /* upto I, minupto I, exact I             */
+  1, 1, 1, 3,                    /* *+I, ++I, ?+I, upto+I                  */
   /* Negative single-char repeats - only for chars < 256                   */
   1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
   3, 3, 3,                       /* NOT upto, minupto, exact               */
-  1, 1, 1, 3,                    /* NOT *+, ++, ?+, updo+                  */
+  1, 1, 1, 3,                    /* NOT *+, ++, ?+, upto+                  */
+  1, 1, 1, 1, 1, 1,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */
+  3, 3, 3,                       /* NOT upto I, minupto I, exact I         */
+  1, 1, 1, 3,                    /* NOT *+I, ++I, ?+I, upto+I              */
   /* Positive type repeats                                                 */
   1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
   3, 3, 3,                       /* Type upto, minupto, exact              */
@@ -144,6 +151,7 @@
   0,                             /* NCLASS                                 */
   0,                             /* XCLASS - variable length               */
   0,                             /* REF                                    */
+  0,                             /* REFI                                   */
   0,                             /* RECURSE                                */
   0,                             /* CALLOUT                                */
   0,                             /* Alt                                    */
@@ -179,18 +187,25 @@
   1, 1,                          /* \P, \p                                 */
   1, 1, 1, 1, 1,                 /* \R, \H, \h, \V, \v                     */
   1,                             /* \X                                     */
-  0, 0, 0, 0, 0,                 /* \Z, \z, Opt, ^, $                      */
+  0, 0, 0, 0, 0, 0,              /* \Z, \z, ^, ^M, $, $M                   */
   1,                             /* Char                                   */
-  1,                             /* Charnc                                 */
+  1,                             /* Chari                                  */
   1,                             /* not                                    */
+  1,                             /* noti                                   */
   /* Positive single-char repeats                                          */
   1, 1, 1, 1, 1, 1,              /* *, *?, +, +?, ?, ??                    */
   1, 1, 1,                       /* upto, minupto, exact                   */
   1, 1, 1, 1,                    /* *+, ++, ?+, upto+                      */
+  1, 1, 1, 1, 1, 1,              /* *I, *?I, +I, +?I, ?I, ??I              */
+  1, 1, 1,                       /* upto I, minupto I, exact I             */
+  1, 1, 1, 1,                    /* *+I, ++I, ?+I, upto+I                  */
   /* Negative single-char repeats - only for chars < 256                   */
   1, 1, 1, 1, 1, 1,              /* NOT *, *?, +, +?, ?, ??                */
   1, 1, 1,                       /* NOT upto, minupto, exact               */
   1, 1, 1, 1,                    /* NOT *+, ++, ?+, upto+                  */
+  1, 1, 1, 1, 1, 1,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */
+  1, 1, 1,                       /* NOT upto I, minupto I, exact I         */
+  1, 1, 1, 1,                    /* NOT *+I, ++I, ?+I, upto+I              */
   /* Positive type repeats                                                 */
   1, 1, 1, 1, 1, 1,              /* Type *, *?, +, +?, ?, ??               */
   1, 1, 1,                       /* Type upto, minupto, exact              */
@@ -202,6 +217,7 @@
   1,                             /* NCLASS                                 */
   1,                             /* XCLASS - variable length               */
   0,                             /* REF                                    */
+  0,                             /* REFI                                   */
   0,                             /* RECURSE                                */
   0,                             /* CALLOUT                                */
   0,                             /* Alt                                    */
@@ -252,7 +268,6 @@
 typedef struct stateblock {
   int offset;                     /* Offset to opcode */
   int count;                      /* Count for repeats */
-  int ims;                        /* ims flag bits */
   int data;                       /* Some use extra data */
 } stateblock;


@@ -308,7 +323,6 @@
   offsetcount       size of same
   workspace         vector of workspace
   wscount           size of same
-  ims               the current ims flags
   rlevel            function call recursion level
   recursing         regex recursive call level


@@ -325,7 +339,6 @@
     { \
     next_active_state->offset = (x); \
     next_active_state->count  = (y); \
-    next_active_state->ims    = ims; \
     next_active_state++; \
     DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
     } \
@@ -336,7 +349,6 @@
     { \
     next_active_state->offset = (x); \
     next_active_state->count  = (y); \
-    next_active_state->ims    = ims; \
     next_active_state->data   = (z); \
     next_active_state++; \
     DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \
@@ -348,7 +360,6 @@
     { \
     next_new_state->offset = (x); \
     next_new_state->count  = (y); \
-    next_new_state->ims    = ims; \
     next_new_state++; \
     DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
     } \
@@ -359,7 +370,6 @@
     { \
     next_new_state->offset = (x); \
     next_new_state->count  = (y); \
-    next_new_state->ims    = ims; \
     next_new_state->data   = (z); \
     next_new_state++; \
     DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \
@@ -378,7 +388,6 @@
   int offsetcount,
   int *workspace,
   int wscount,
-  int ims,
   int  rlevel,
   int  recursing)
 {
@@ -605,6 +614,7 @@
   for (i = 0; i < active_count; i++)
     {
     stateblock *current_state = active_states + i;
+    BOOL caseless = FALSE; 
     const uschar *code;
     int state_offset = current_state->offset;
     int count, codevalue, rrc;
@@ -616,10 +626,6 @@
         else printf("0x%02x\n", c);
 #endif


-    /* This variable is referred to implicity in the ADD_xxx macros. */
-
-    ims = current_state->ims;
-
     /* A negative offset is a special case meaning "hold off going to this
     (negated) state until the number of characters in the data field have
     been skipped". */
@@ -822,10 +828,14 @@


       /*-----------------------------------------------------------------*/
       case OP_CIRC:
+      if (ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0)
+        { ADD_ACTIVE(state_offset + 1, 0); }
+      break;
+
+      /*-----------------------------------------------------------------*/
+      case OP_CIRCM:
       if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||
-          ((ims & PCRE_MULTILINE) != 0 &&
-            ptr != end_subject &&
-            WAS_NEWLINE(ptr)))
+          (ptr != end_subject && WAS_NEWLINE(ptr)))
         { ADD_ACTIVE(state_offset + 1, 0); }
       break;


@@ -840,12 +850,6 @@
       break;


       /*-----------------------------------------------------------------*/
-      case OP_OPT:
-      ims = code[1];
-      ADD_ACTIVE(state_offset + 2, 0);
-      break;
-
-      /*-----------------------------------------------------------------*/
       case OP_SOD:
       if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); }
       break;
@@ -890,11 +894,23 @@
           could_continue = TRUE;
         else if (clen == 0 ||
             ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&
-               ((ims & PCRE_MULTILINE) != 0 || ptr == end_subject - md->nllen)
+               (ptr == end_subject - md->nllen)
             ))
           { ADD_ACTIVE(state_offset + 1, 0); }
         }
-      else if ((ims & PCRE_MULTILINE) != 0 && IS_NEWLINE(ptr))
+      break;
+
+      /*-----------------------------------------------------------------*/
+      case OP_DOLLM:
+      if ((md->moptions & PCRE_NOTEOL) == 0)
+        {
+        if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+          could_continue = TRUE;
+        else if (clen == 0 ||
+            ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))
+          { ADD_ACTIVE(state_offset + 1, 0); }
+        }
+      else if (IS_NEWLINE(ptr))
         { ADD_ACTIVE(state_offset + 1, 0); }
       break;


@@ -1950,7 +1966,7 @@
       break;


       /*-----------------------------------------------------------------*/
-      case OP_CHARNC:
+      case OP_CHARI:
       if (clen == 0) break;


 #ifdef SUPPORT_UTF8
@@ -2136,19 +2152,35 @@
       break;


       /*-----------------------------------------------------------------*/
-      /* Match a negated single character. This is only used for one-byte
-      characters, that is, we know that d < 256. The character we are
+      /* Match a negated single character casefully. This is only used for
+      one-byte characters, that is, we know that d < 256. The character we are
       checking (c) can be multibyte. */


       case OP_NOT:
-      if (clen > 0)
-        {
-        unsigned int otherd = ((ims & PCRE_CASELESS) != 0)? fcc[d] : d;
-        if (c != d && c != otherd) { ADD_NEW(state_offset + dlen + 1, 0); }
-        }
+      if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); }
       break;


       /*-----------------------------------------------------------------*/
+      /* Match a negated single character caselessly. This is only used for
+      one-byte characters, that is, we know that d < 256. The character we are
+      checking (c) can be multibyte. */
+
+      case OP_NOTI:
+      if (clen > 0 && c != d && c != fcc[d]) 
+        { ADD_NEW(state_offset + dlen + 1, 0); }
+      break;
+
+      /*-----------------------------------------------------------------*/
+      case OP_PLUSI:
+      case OP_MINPLUSI:
+      case OP_POSPLUSI:
+      case OP_NOTPLUSI:
+      case OP_NOTMINPLUSI:
+      case OP_NOTPOSPLUSI:
+      caseless = TRUE;
+      codevalue -= OP_STARI - OP_STAR;
+ 
+      /* Fall through */
       case OP_PLUS:
       case OP_MINPLUS:
       case OP_POSPLUS:
@@ -2160,7 +2192,7 @@
       if (clen > 0)
         {
         unsigned int otherd = NOTACHAR;
-        if ((ims & PCRE_CASELESS) != 0)
+        if (caseless)
           {
 #ifdef SUPPORT_UTF8
           if (utf8 && d >= 128)
@@ -2188,6 +2220,15 @@
       break;


       /*-----------------------------------------------------------------*/
+      case OP_QUERYI:
+      case OP_MINQUERYI:
+      case OP_POSQUERYI:
+      case OP_NOTQUERYI:
+      case OP_NOTMINQUERYI:
+      case OP_NOTPOSQUERYI:
+      caseless = TRUE;
+      codevalue -= OP_STARI - OP_STAR;
+      /* Fall through */
       case OP_QUERY:
       case OP_MINQUERY:
       case OP_POSQUERY:
@@ -2198,7 +2239,7 @@
       if (clen > 0)
         {
         unsigned int otherd = NOTACHAR;
-        if ((ims & PCRE_CASELESS) != 0)
+        if (caseless)
           {
 #ifdef SUPPORT_UTF8
           if (utf8 && d >= 128)
@@ -2224,6 +2265,15 @@
       break;


       /*-----------------------------------------------------------------*/
+      case OP_STARI:
+      case OP_MINSTARI:
+      case OP_POSSTARI:
+      case OP_NOTSTARI:
+      case OP_NOTMINSTARI:
+      case OP_NOTPOSSTARI:
+      caseless = TRUE;
+      codevalue -= OP_STARI - OP_STAR;
+      /* Fall through */
       case OP_STAR:
       case OP_MINSTAR:
       case OP_POSSTAR:
@@ -2234,7 +2284,7 @@
       if (clen > 0)
         {
         unsigned int otherd = NOTACHAR;
-        if ((ims & PCRE_CASELESS) != 0)
+        if (caseless)
           {
 #ifdef SUPPORT_UTF8
           if (utf8 && d >= 128)
@@ -2260,13 +2310,18 @@
       break;


       /*-----------------------------------------------------------------*/
+      case OP_EXACTI:
+      case OP_NOTEXACTI:
+      caseless = TRUE;
+      codevalue -= OP_STARI - OP_STAR;
+      /* Fall through */
       case OP_EXACT:
       case OP_NOTEXACT:
       count = current_state->count;  /* Number already matched */
       if (clen > 0)
         {
         unsigned int otherd = NOTACHAR;
-        if ((ims & PCRE_CASELESS) != 0)
+        if (caseless)
           {
 #ifdef SUPPORT_UTF8
           if (utf8 && d >= 128)
@@ -2290,6 +2345,15 @@
       break;


       /*-----------------------------------------------------------------*/
+      case OP_UPTOI:
+      case OP_MINUPTOI:
+      case OP_POSUPTOI:
+      case OP_NOTUPTOI:
+      case OP_NOTMINUPTOI:
+      case OP_NOTPOSUPTOI:
+      caseless = TRUE;
+      codevalue -= OP_STARI - OP_STAR;
+      /* Fall through */
       case OP_UPTO:
       case OP_MINUPTO:
       case OP_POSUPTO:
@@ -2301,7 +2365,7 @@
       if (clen > 0)
         {
         unsigned int otherd = NOTACHAR;
-        if ((ims & PCRE_CASELESS) != 0)
+        if (caseless)
           {
 #ifdef SUPPORT_UTF8
           if (utf8 && d >= 128)
@@ -2444,7 +2508,6 @@
           sizeof(local_offsets)/sizeof(int),    /* size of same */
           local_workspace,                      /* workspace vector */
           sizeof(local_workspace)/sizeof(int),  /* size of same */
-          ims,                                  /* the current ims flags */
           rlevel,                               /* function recursion level */
           recursing);                           /* pass on regex recursion */


@@ -2535,7 +2598,6 @@
             sizeof(local_offsets)/sizeof(int),    /* size of same */
             local_workspace,                      /* workspace vector */
             sizeof(local_workspace)/sizeof(int),  /* size of same */
-            ims,                                  /* the current ims flags */
             rlevel,                               /* function recursion level */
             recursing);                           /* pass on regex recursion */


@@ -2568,7 +2630,6 @@
           sizeof(local_offsets)/sizeof(int),    /* size of same */
           local_workspace,                      /* workspace vector */
           sizeof(local_workspace)/sizeof(int),  /* size of same */
-          ims,                                  /* the current ims flags */
           rlevel,                               /* function recursion level */
           recursing + 1);                       /* regex recurse level */


@@ -2620,7 +2681,6 @@
           sizeof(local_offsets)/sizeof(int),    /* size of same */
           local_workspace,                      /* workspace vector */
           sizeof(local_workspace)/sizeof(int),  /* size of same */
-          ims,                                  /* the current ims flags */
           rlevel,                               /* function recursion level */
           recursing);                           /* pass on regex recursion */


@@ -3227,7 +3287,6 @@
     offsetcount,                       /* size of same */
     workspace,                         /* workspace vector */
     wscount,                           /* size of same */
-    re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL), /* ims flags */
     0,                                 /* function recurse level */
     0);                                /* regex recurse level */



Modified: code/trunk/pcre_exec.c
===================================================================
--- code/trunk/pcre_exec.c    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/pcre_exec.c    2011-05-25 08:29:03 UTC (rev 602)
@@ -142,14 +142,14 @@
   eptr        pointer into the subject
   length      length of reference to be matched (number of bytes)
   md          points to match data block
-  ims         the ims flags
+  caseless    TRUE if caseless


 Returns:      < 0 if not matched, otherwise the number of subject bytes matched
 */


static int
match_ref(int offset, register USPTR eptr, int length, match_data *md,
- unsigned long int ims)
+ BOOL caseless)
{
USPTR eptr_start = eptr;
register USPTR p = md->start_subject + md->offset_vector[offset];
@@ -175,7 +175,7 @@
properly if Unicode properties are supported. Otherwise, we can check only
ASCII characters. */

-if ((ims & PCRE_CASELESS) != 0)
+if (caseless)
{
#ifdef SUPPORT_UTF8
#ifdef SUPPORT_UCP
@@ -283,10 +283,10 @@
#define REGISTER register

#ifdef PCRE_DEBUG
-#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \
+#define RMATCH(ra,rb,rc,rd,re,rf,rw) \
{ \
printf("match() called in line %d\n", __LINE__); \
- rrc = match(ra,rb,mstart,markptr,rc,rd,re,rf,rg,rdepth+1); \
+ rrc = match(ra,rb,mstart,markptr,rc,rd,re,rf,rdepth+1); \
printf("to line %d\n", __LINE__); \
}
#define RRETURN(ra) \
@@ -295,8 +295,8 @@
return ra; \
}
#else
-#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \
- rrc = match(ra,rb,mstart,markptr,rc,rd,re,rf,rg,rdepth+1)
+#define RMATCH(ra,rb,rc,rd,re,rf,rw) \
+ rrc = match(ra,rb,mstart,markptr,rc,rd,re,rf,rdepth+1)
#define RRETURN(ra) return ra
#endif

@@ -309,7 +309,7 @@

#define REGISTER

-#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw)\
+#define RMATCH(ra,rb,rc,rd,re,rf,rw)\
{\
heapframe *newframe = (heapframe *)(pcre_stack_malloc)(sizeof(heapframe));\
if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\
@@ -319,9 +319,8 @@
newframe->Xmstart = mstart;\
newframe->Xmarkptr = markptr;\
newframe->Xoffset_top = rc;\
- newframe->Xims = re;\
- newframe->Xeptrb = rf;\
- newframe->Xflags = rg;\
+ newframe->Xeptrb = re;\
+ newframe->Xflags = rf;\
newframe->Xrdepth = frame->Xrdepth + 1;\
newframe->Xprevframe = frame;\
frame = newframe;\
@@ -357,7 +356,6 @@
USPTR Xmstart;
USPTR Xmarkptr;
int Xoffset_top;
- long int Xims;
eptrblock *Xeptrb;
int Xflags;
unsigned int Xrdepth;
@@ -380,8 +378,6 @@
BOOL Xcondition;
BOOL Xprev_is_word;

-  unsigned long int Xoriginal_ims;
-
 #ifdef SUPPORT_UCP
   int Xprop_type;
   int Xprop_value;
@@ -467,7 +463,6 @@
    markptr     pointer to the most recent MARK name, or NULL
    offset_top  current top pointer
    md          pointer to "static" info for the match
-   ims         current /i, /m, and /s options
    eptrb       pointer to chain of blocks containing eptr at start of
                  brackets - for testing for empty matches
    flags       can contain
@@ -485,8 +480,8 @@


 static int
 match(REGISTER USPTR eptr, REGISTER const uschar *ecode, USPTR mstart,
-  const uschar *markptr, int offset_top, match_data *md, unsigned long int ims,
-  eptrblock *eptrb, int flags, unsigned int rdepth)
+  const uschar *markptr, int offset_top, match_data *md, eptrblock *eptrb, 
+  int flags, unsigned int rdepth)
 {
 /* These variables do not need to be preserved over recursion in this function,
 so they can be ordinary variables in all cases. Mark some of them with
@@ -498,6 +493,7 @@
 register BOOL utf8;        /* Local copy of UTF-8 flag for speed */


BOOL minimize, possessive; /* Quantifier options */
+BOOL caseless;
int condcode;

 /* When recursion is not being used, all "local" variables that have to be
@@ -517,7 +513,6 @@
 frame->Xmstart = mstart;
 frame->Xmarkptr = markptr;
 frame->Xoffset_top = offset_top;
-frame->Xims = ims;
 frame->Xeptrb = eptrb;
 frame->Xflags = flags;
 frame->Xrdepth = rdepth;
@@ -533,7 +528,6 @@
 #define mstart             frame->Xmstart
 #define markptr            frame->Xmarkptr
 #define offset_top         frame->Xoffset_top
-#define ims                frame->Xims
 #define eptrb              frame->Xeptrb
 #define flags              frame->Xflags
 #define rdepth             frame->Xrdepth
@@ -557,8 +551,6 @@
 #define condition          frame->Xcondition
 #define prev_is_word       frame->Xprev_is_word


-#define original_ims       frame->Xoriginal_ims
-
 #ifdef SUPPORT_UCP
 #define prop_type          frame->Xprop_type
 #define prop_value         frame->Xprop_value
@@ -612,8 +604,6 @@
 BOOL condition;
 BOOL prev_is_word;


-unsigned long int original_ims;
-
#ifdef SUPPORT_UCP
int prop_type;
int prop_value;
@@ -676,8 +666,6 @@
if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT);
if (rdepth >= md->match_limit_recursion) RRETURN(PCRE_ERROR_RECURSIONLIMIT);

-original_ims = ims;    /* Save for resetting on ')' */
-
 /* At the start of a group with an unlimited repeat that may match an empty
 string, the match_cbegroup flag is set. When this is the case, add the current
 subject pointer to the chain of such remembered pointers, to be checked when we
@@ -706,7 +694,7 @@
     case OP_MARK:
     markptr = ecode + 2;
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
-      ims, eptrb, flags, RM55);
+      eptrb, flags, RM55);


     /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an
     argument, and we must check whether that argument matches this MARK's
@@ -732,7 +720,7 @@


     case OP_COMMIT:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
-      ims, eptrb, flags, RM52);
+      eptrb, flags, RM52);
     if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE &&
         rrc != MATCH_SKIP && rrc != MATCH_SKIP_ARG &&
         rrc != MATCH_THEN)
@@ -743,13 +731,13 @@


     case OP_PRUNE:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
-      ims, eptrb, flags, RM51);
+      eptrb, flags, RM51);
     if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
     MRRETURN(MATCH_PRUNE);


     case OP_PRUNE_ARG:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
-      ims, eptrb, flags, RM56);
+      eptrb, flags, RM56);
     if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
     md->mark = ecode + 2;
     RRETURN(MATCH_PRUNE);
@@ -758,7 +746,7 @@


     case OP_SKIP:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
-      ims, eptrb, flags, RM53);
+      eptrb, flags, RM53);
     if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
       RRETURN(rrc);
     md->start_match_ptr = eptr;   /* Pass back current position */
@@ -766,7 +754,7 @@


     case OP_SKIP_ARG:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
-      ims, eptrb, flags, RM57);
+      eptrb, flags, RM57);
     if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
       RRETURN(rrc);


@@ -785,14 +773,14 @@

     case OP_THEN:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
-      ims, eptrb, flags, RM54);
+      eptrb, flags, RM54);
     if (rrc != MATCH_NOMATCH) RRETURN(rrc);
     md->start_match_ptr = ecode - GET(ecode, 1);
     MRRETURN(MATCH_THEN);


     case OP_THEN_ARG:
     RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1+LINK_SIZE],
-      offset_top, md, ims, eptrb, flags, RM58);
+      offset_top, md, eptrb, flags, RM58);
     if (rrc != MATCH_NOMATCH) RRETURN(rrc);
     md->start_match_ptr = ecode - GET(ecode, 1);
     md->mark = ecode + LINK_SIZE + 2;
@@ -839,7 +827,7 @@
       do
         {
         RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
-          ims, eptrb, flags, RM1);
+          eptrb, flags, RM1);
         if (rrc != MATCH_NOMATCH &&
             (rrc != MATCH_THEN || md->start_match_ptr != ecode))
           RRETURN(rrc);
@@ -892,8 +880,8 @@


         /* Possibly empty group; can't use tail recursion. */


-        RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,
-          eptrb, flags, RM48);
+        RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, eptrb, 
+          flags, RM48);
         if (rrc == MATCH_NOMATCH) md->mark = markptr;
         RRETURN(rrc);
         }
@@ -901,8 +889,8 @@
       /* For non-final alternatives, continue the loop for a NOMATCH result;
       otherwise return. */


-      RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,
-        eptrb, flags, RM2);
+      RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, eptrb, 
+        flags, RM2);
       if (rrc != MATCH_NOMATCH &&
           (rrc != MATCH_THEN || md->start_match_ptr != ecode))
         RRETURN(rrc);
@@ -1098,7 +1086,7 @@


     else
       {
-      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL,
+      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL,
           match_condassert, RM3);
       if (rrc == MATCH_MATCH)
         {
@@ -1128,7 +1116,7 @@
       ecode += 1 + LINK_SIZE;
       if (op == OP_SCOND)        /* Possibly empty group */
         {
-        RMATCH(eptr, ecode, offset_top, md, ims, eptrb, match_cbegroup, RM49);
+        RMATCH(eptr, ecode, offset_top, md, eptrb, match_cbegroup, RM49);
         RRETURN(rrc);
         }
       else                       /* Group must match something */
@@ -1182,7 +1170,6 @@
       memmove(md->offset_vector, rec->offset_save,
         rec->saved_max * sizeof(int));
       offset_top = rec->save_offset_top;
-      ims = original_ims;
       ecode = rec->after_call;
       break;
       }
@@ -1210,14 +1197,6 @@
     rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT;
     MRRETURN(rrc);


-    /* Change option settings */
-
-    case OP_OPT:
-    ims = ecode[1];
-    ecode += 2;
-    DPRINTF(("ims set to %02lx\n", ims));
-    break;
-
     /* Assertion brackets. Check the alternative branches in turn - the
     matching won't pass the KET for an assertion. If any one branch matches,
     the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
@@ -1228,7 +1207,7 @@
     case OP_ASSERTBACK:
     do
       {
-      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,
+      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, 0,
         RM4);
       if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
         {
@@ -1263,7 +1242,7 @@
     case OP_ASSERTBACK_NOT:
     do
       {
-      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,
+      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, 0,
         RM5);
       if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) MRRETURN(MATCH_NOMATCH);
       if (rrc == MATCH_SKIP || rrc == MATCH_PRUNE || rrc == MATCH_COMMIT)
@@ -1401,7 +1380,7 @@
       do
         {
         RMATCH(eptr, callpat + _pcre_OP_lengths[*callpat], offset_top,
-          md, ims, eptrb, flags, RM6);
+          md, eptrb, flags, RM6);
         if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
           {
           DPRINTF(("Recursion matched\n"));
@@ -1448,7 +1427,7 @@


     do
       {
-      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM7);
+      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, 0, RM7);
       if (rrc == MATCH_MATCH)  /* Note: _not_ MATCH_ACCEPT */
         {
         mstart = md->start_match_ptr;
@@ -1487,19 +1466,11 @@


     /* The repeating kets try the rest of the pattern or restart from the
     preceding bracket, in the appropriate order. The second "call" of match()
-    uses tail recursion, to avoid using another stack frame. We need to reset
-    any options that changed within the bracket before re-running it, so
-    check the next opcode. */
+    uses tail recursion, to avoid using another stack frame. */


-    if (ecode[1+LINK_SIZE] == OP_OPT)
-      {
-      ims = (ims & ~PCRE_IMS) | ecode[4];
-      DPRINTF(("ims set to %02lx at group repeat\n", ims));
-      }
-
     if (*ecode == OP_KETRMIN)
       {
-      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM8);
+      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, 0, RM8);
       if (rrc != MATCH_NOMATCH) RRETURN(rrc);
       ecode = prev;
       flags = 0;
@@ -1507,7 +1478,7 @@
       }
     else  /* OP_KETRMAX */
       {
-      RMATCH(eptr, prev, offset_top, md, ims, eptrb, match_cbegroup, RM9);
+      RMATCH(eptr, prev, offset_top, md, eptrb, match_cbegroup, RM9);
       if (rrc != MATCH_NOMATCH) RRETURN(rrc);
       ecode += 1 + LINK_SIZE;
       flags = 0;
@@ -1531,7 +1502,7 @@
     case OP_BRAZERO:
       {
       next = ecode+1;
-      RMATCH(eptr, next, offset_top, md, ims, eptrb, 0, RM10);
+      RMATCH(eptr, next, offset_top, md, eptrb, 0, RM10);
       if (rrc != MATCH_NOMATCH) RRETURN(rrc);
       do next += GET(next,1); while (*next == OP_ALT);
       ecode = next + 1 + LINK_SIZE;
@@ -1542,7 +1513,7 @@
       {
       next = ecode+1;
       do next += GET(next, 1); while (*next == OP_ALT);
-      RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0, RM11);
+      RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, eptrb, 0, RM11);
       if (rrc != MATCH_NOMATCH) RRETURN(rrc);
       ecode++;
       }
@@ -1626,17 +1597,10 @@
           rec->saved_max * sizeof(int));
         offset_top = rec->save_offset_top;
         ecode = rec->after_call;
-        ims = original_ims;
         break;
         }
       }


-    /* For both capturing and non-capturing groups, reset the value of the ims
-    flags, in case they got changed during the group. */
-
-    ims = original_ims;
-    DPRINTF(("ims reset to %02lx\n", ims));
-
     /* For a non-repeating ket, just continue at this level. This also
     happens for a repeating ket if no characters were matched in the group.
     This is the forcible breaking of infinite loops as implemented in Perl
@@ -1658,11 +1622,11 @@


     if (*ecode == OP_KETRMIN)
       {
-      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM12);
+      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, 0, RM12);
       if (rrc != MATCH_NOMATCH) RRETURN(rrc);
       if (flags != 0)    /* Could match an empty string */
         {
-        RMATCH(eptr, prev, offset_top, md, ims, eptrb, flags, RM50);
+        RMATCH(eptr, prev, offset_top, md, eptrb, flags, RM50);
         RRETURN(rrc);
         }
       ecode = prev;
@@ -1670,7 +1634,7 @@
       }
     else  /* OP_KETRMAX */
       {
-      RMATCH(eptr, prev, offset_top, md, ims, eptrb, flags, RM13);
+      RMATCH(eptr, prev, offset_top, md, eptrb, flags, RM13);
       if (rrc != MATCH_NOMATCH) RRETURN(rrc);
       ecode += 1 + LINK_SIZE;
       flags = 0;
@@ -1678,27 +1642,28 @@
       }
     /* Control never gets here */


-    /* Start of subject unless notbol, or after internal newline if multiline */
+    /* Not multiline mode: start of subject assertion, unless notbol. */


     case OP_CIRC:
     if (md->notbol && eptr == md->start_subject) MRRETURN(MATCH_NOMATCH);
-    if ((ims & PCRE_MULTILINE) != 0)
-      {
-      if (eptr != md->start_subject &&
-          (eptr == md->end_subject || !WAS_NEWLINE(eptr)))
-        MRRETURN(MATCH_NOMATCH);
-      ecode++;
-      break;
-      }
-    /* ... else fall through */
-
+     
     /* Start of subject assertion */


     case OP_SOD:
     if (eptr != md->start_subject) MRRETURN(MATCH_NOMATCH);
     ecode++;
     break;
+    
+    /* Multiline mode: start of subject unless notbol, or after any newline. */


+    case OP_CIRCM:
+    if (md->notbol && eptr == md->start_subject) MRRETURN(MATCH_NOMATCH);
+    if (eptr != md->start_subject &&
+        (eptr == md->end_subject || !WAS_NEWLINE(eptr)))
+      MRRETURN(MATCH_NOMATCH);
+    ecode++;
+    break;
+
     /* Start of match assertion */


     case OP_SOM:
@@ -1713,28 +1678,27 @@
     ecode++;
     break;


-    /* Assert before internal newline if multiline, or before a terminating
-    newline unless endonly is set, else end of subject unless noteol is set. */
+    /* Multiline mode: assert before any newline, or before end of subject
+    unless noteol is set. */


-    case OP_DOLL:
-    if ((ims & PCRE_MULTILINE) != 0)
+    case OP_DOLLM:
+    if (eptr < md->end_subject)
+      { if (!IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); }
+    else
       {
-      if (eptr < md->end_subject)
-        { if (!IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); }
-      else
-        {
-        if (md->noteol) MRRETURN(MATCH_NOMATCH);
-        SCHECK_PARTIAL();
-        }
-      ecode++;
-      break;
-      }
-    else  /* Not multiline */
-      {
       if (md->noteol) MRRETURN(MATCH_NOMATCH);
-      if (!md->endonly) goto ASSERT_NL_OR_EOS;
+      SCHECK_PARTIAL();
       }
+    ecode++;
+    break;


+    /* Not multiline mode: assert before a terminating newline or before end of 
+    subject unless noteol is set. */
+
+    case OP_DOLL:
+    if (md->noteol) MRRETURN(MATCH_NOMATCH);
+    if (!md->endonly) goto ASSERT_NL_OR_EOS;
+
     /* ... else fall through for endonly */


     /* End of subject assertion (\z) */
@@ -2270,6 +2234,8 @@
     loops). */


     case OP_REF:
+    case OP_REFI: 
+    caseless = op == OP_REFI; 
     offset = GET2(ecode, 1) << 1;               /* Doubled ref number */
     ecode += 3;


@@ -2317,7 +2283,7 @@
       break;


       default:               /* No repeat follows */
-      if ((length = match_ref(offset, eptr, length, md, ims)) < 0)
+      if ((length = match_ref(offset, eptr, length, md, caseless)) < 0)
         {
         CHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
@@ -2338,7 +2304,7 @@
     for (i = 1; i <= min; i++)
       {
       int slength; 
-      if ((slength = match_ref(offset, eptr, length, md, ims)) < 0)
+      if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
         {
         CHECK_PARTIAL();
         MRRETURN(MATCH_NOMATCH);
@@ -2358,10 +2324,10 @@
       for (fi = min;; fi++)
         {
         int slength; 
-        RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14);
+        RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM14);
         if (rrc != MATCH_NOMATCH) RRETURN(rrc);
         if (fi >= max) MRRETURN(MATCH_NOMATCH);
-        if ((slength = match_ref(offset, eptr, length, md, ims)) < 0)
+        if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
           {
           CHECK_PARTIAL();
           MRRETURN(MATCH_NOMATCH);
@@ -2379,7 +2345,7 @@
       for (i = min; i < max; i++)
         {
         int slength; 
-        if ((slength = match_ref(offset, eptr, length, md, ims)) < 0)
+        if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
           {
           CHECK_PARTIAL();
           break;
@@ -2388,7 +2354,7 @@
         }
       while (eptr >= pp)
         {
-        RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM15);
+        RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM15);
         if (rrc != MATCH_NOMATCH) RRETURN(rrc);
         eptr -= length;
         }
@@ -2498,7 +2464,7 @@
           {
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM16);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -2523,7 +2489,7 @@
           {
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM17);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -2569,7 +2535,7 @@
             }
           for (;;)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM18);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM18);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (eptr-- == pp) break;        /* Stop if tried at original pos */
             BACKCHAR(eptr);
@@ -2592,7 +2558,7 @@
             }
           while (eptr >= pp)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM19);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM19);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             eptr--;
             }
@@ -2668,7 +2634,7 @@
         {
         for (fi = min;; fi++)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM20);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
@@ -2701,7 +2667,7 @@
           }
         for(;;)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM21);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM21);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (eptr-- == pp) break;        /* Stop if tried at original pos */
           if (utf8) BACKCHAR(eptr);
@@ -2746,7 +2712,7 @@


     /* Match a single character, caselessly */


-    case OP_CHARNC:
+    case OP_CHARI:
 #ifdef SUPPORT_UTF8
     if (utf8)
       {
@@ -2806,23 +2772,28 @@
     /* Match a single character repeatedly. */


     case OP_EXACT:
+    case OP_EXACTI:
     min = max = GET2(ecode, 1);
     ecode += 3;
     goto REPEATCHAR;


     case OP_POSUPTO:
+    case OP_POSUPTOI:
     possessive = TRUE;
     /* Fall through */


     case OP_UPTO:
+    case OP_UPTOI:
     case OP_MINUPTO:
+    case OP_MINUPTOI:
     min = 0;
     max = GET2(ecode, 1);
-    minimize = *ecode == OP_MINUPTO;
+    minimize = *ecode == OP_MINUPTO || *ecode == OP_MINUPTOI;
     ecode += 3;
     goto REPEATCHAR;


     case OP_POSSTAR:
+    case OP_POSSTARI:
     possessive = TRUE;
     min = 0;
     max = INT_MAX;
@@ -2830,6 +2801,7 @@
     goto REPEATCHAR;


     case OP_POSPLUS:
+    case OP_POSPLUSI:
     possessive = TRUE;
     min = 1;
     max = INT_MAX;
@@ -2837,6 +2809,7 @@
     goto REPEATCHAR;


     case OP_POSQUERY:
+    case OP_POSQUERYI:
     possessive = TRUE;
     min = 0;
     max = 1;
@@ -2844,14 +2817,19 @@
     goto REPEATCHAR;


     case OP_STAR:
+    case OP_STARI:
     case OP_MINSTAR:
+    case OP_MINSTARI:
     case OP_PLUS:
+    case OP_PLUSI:
     case OP_MINPLUS:
+    case OP_MINPLUSI:
     case OP_QUERY:
+    case OP_QUERYI:
     case OP_MINQUERY:
-    c = *ecode++ - OP_STAR;
+    case OP_MINQUERYI:
+    c = *ecode++ - ((op < OP_STARI)? OP_STAR : OP_STARI);
     minimize = (c & 1) != 0;
-
     min = rep_min[c];                 /* Pick up values from tables; */
     max = rep_max[c];                 /* zero for max => infinity */
     if (max == 0) max = INT_MAX;
@@ -2874,7 +2852,7 @@
         {
 #ifdef SUPPORT_UCP
         unsigned int othercase;
-        if ((ims & PCRE_CASELESS) != 0 &&
+        if (op >= OP_STARI &&     /* Caseless */
             (othercase = UCD_OTHERCASE(fc)) != fc)
           oclength = _pcre_ord2utf8(othercase, occhars);
         else oclength = 0;
@@ -2902,7 +2880,7 @@
           {
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM22);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr <= md->end_subject - length &&
@@ -2944,7 +2922,7 @@


           for(;;)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM23);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (eptr == pp) { MRRETURN(MATCH_NOMATCH); }
 #ifdef SUPPORT_UCP
@@ -2981,7 +2959,7 @@
     DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max,
       max, eptr));


-    if ((ims & PCRE_CASELESS) != 0)
+    if (op >= OP_STARI)  /* Caseless */
       {
       fc = md->lcc[fc];
       for (i = 1; i <= min; i++)
@@ -2998,7 +2976,7 @@
         {
         for (fi = min;; fi++)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM24);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
@@ -3028,7 +3006,7 @@


         while (eptr >= pp)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM25);
           eptr--;
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           }
@@ -3057,7 +3035,7 @@
         {
         for (fi = min;; fi++)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM26);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
@@ -3086,7 +3064,7 @@


         while (eptr >= pp)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM27);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM27);
           eptr--;
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           }
@@ -3099,6 +3077,7 @@
     checking can be multibyte. */


     case OP_NOT:
+    case OP_NOTI: 
     if (eptr >= md->end_subject)
       {
       SCHECK_PARTIAL();
@@ -3106,7 +3085,7 @@
       }
     ecode++;
     GETCHARINCTEST(c, eptr);
-    if ((ims & PCRE_CASELESS) != 0)
+    if (op == OP_NOTI)         /* The caseless case */
       {
 #ifdef SUPPORT_UTF8
       if (c < 256)
@@ -3114,7 +3093,7 @@
       c = md->lcc[c];
       if (md->lcc[*ecode++] == c) MRRETURN(MATCH_NOMATCH);
       }
-    else
+    else    /* Caseful */
       {
       if (*ecode++ == c) MRRETURN(MATCH_NOMATCH);
       }
@@ -3128,19 +3107,23 @@
     about... */


     case OP_NOTEXACT:
+    case OP_NOTEXACTI:
     min = max = GET2(ecode, 1);
     ecode += 3;
     goto REPEATNOTCHAR;


     case OP_NOTUPTO:
+    case OP_NOTUPTOI:
     case OP_NOTMINUPTO:
+    case OP_NOTMINUPTOI:
     min = 0;
     max = GET2(ecode, 1);
-    minimize = *ecode == OP_NOTMINUPTO;
+    minimize = *ecode == OP_NOTMINUPTO || *ecode == OP_NOTMINUPTOI;
     ecode += 3;
     goto REPEATNOTCHAR;


     case OP_NOTPOSSTAR:
+    case OP_NOTPOSSTARI:
     possessive = TRUE;
     min = 0;
     max = INT_MAX;
@@ -3148,6 +3131,7 @@
     goto REPEATNOTCHAR;


     case OP_NOTPOSPLUS:
+    case OP_NOTPOSPLUSI:
     possessive = TRUE;
     min = 1;
     max = INT_MAX;
@@ -3155,6 +3139,7 @@
     goto REPEATNOTCHAR;


     case OP_NOTPOSQUERY:
+    case OP_NOTPOSQUERYI:
     possessive = TRUE;
     min = 0;
     max = 1;
@@ -3162,6 +3147,7 @@
     goto REPEATNOTCHAR;


     case OP_NOTPOSUPTO:
+    case OP_NOTPOSUPTOI:
     possessive = TRUE;
     min = 0;
     max = GET2(ecode, 1);
@@ -3169,12 +3155,18 @@
     goto REPEATNOTCHAR;


     case OP_NOTSTAR:
+    case OP_NOTSTARI:
     case OP_NOTMINSTAR:
+    case OP_NOTMINSTARI:
     case OP_NOTPLUS:
+    case OP_NOTPLUSI:
     case OP_NOTMINPLUS:
+    case OP_NOTMINPLUSI:
     case OP_NOTQUERY:
+    case OP_NOTQUERYI:
     case OP_NOTMINQUERY:
-    c = *ecode++ - OP_NOTSTAR;
+    case OP_NOTMINQUERYI:
+    c = *ecode++ - ((op >= OP_NOTSTARI)? OP_NOTSTARI: OP_NOTSTAR);
     minimize = (c & 1) != 0;
     min = rep_min[c];                 /* Pick up values from tables; */
     max = rep_max[c];                 /* zero for max => infinity */
@@ -3196,7 +3188,7 @@
     DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max,
       max, eptr));


-    if ((ims & PCRE_CASELESS) != 0)
+    if (op >= OP_NOTSTARI)     /* Caseless */
       {
       fc = md->lcc[fc];


@@ -3244,7 +3236,7 @@
           register unsigned int d;
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM28);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -3263,7 +3255,7 @@
           {
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM29);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -3304,7 +3296,7 @@
         if (possessive) continue;
         for(;;)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM30);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM30);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (eptr-- == pp) break;        /* Stop if tried at original pos */
             BACKCHAR(eptr);
@@ -3327,7 +3319,7 @@
           if (possessive) continue;
           while (eptr >= pp)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM31);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM31);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             eptr--;
             }
@@ -3384,7 +3376,7 @@
           register unsigned int d;
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM32);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -3402,7 +3394,7 @@
           {
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM33);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -3442,7 +3434,7 @@
           if (possessive) continue;
           for(;;)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM34);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM34);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (eptr-- == pp) break;        /* Stop if tried at original pos */
             BACKCHAR(eptr);
@@ -3465,7 +3457,7 @@
           if (possessive) continue;
           while (eptr >= pp)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM35);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM35);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             eptr--;
             }
@@ -4263,7 +4255,7 @@
           case PT_ANY:
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM36);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -4279,7 +4271,7 @@
           case PT_LAMP:
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM37);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -4299,7 +4291,7 @@
           case PT_GC:
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM38);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -4317,7 +4309,7 @@
           case PT_PC:
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM39);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -4335,7 +4327,7 @@
           case PT_SC:
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM40);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -4353,7 +4345,7 @@
           case PT_ALNUM:
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM59);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM59);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -4372,7 +4364,7 @@
           case PT_SPACE:    /* Perl space */
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM60);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM60);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -4392,7 +4384,7 @@
           case PT_PXSPACE:  /* POSIX space */
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM61);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM61);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -4412,7 +4404,7 @@
           case PT_WORD:
           for (fi = min;; fi++)
             {
-            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM62);
+            RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM62);
             if (rrc != MATCH_NOMATCH) RRETURN(rrc);
             if (fi >= max) MRRETURN(MATCH_NOMATCH);
             if (eptr >= md->end_subject)
@@ -4444,7 +4436,7 @@
         {
         for (fi = min;; fi++)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM41);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
@@ -4476,7 +4468,7 @@
         {
         for (fi = min;; fi++)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM42);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
@@ -4639,7 +4631,7 @@
         {
         for (fi = min;; fi++)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM43);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (fi >= max) MRRETURN(MATCH_NOMATCH);
           if (eptr >= md->end_subject)
@@ -4937,7 +4929,7 @@
         if (possessive) continue;
         for(;;)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM44);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM44);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (eptr-- == pp) break;        /* Stop if tried at original pos */
           if (utf8) BACKCHAR(eptr);
@@ -4978,7 +4970,7 @@


         for(;;)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM45);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM45);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (eptr-- == pp) break;        /* Stop if tried at original pos */
           for (;;)                        /* Move back over one extended */
@@ -5271,7 +5263,7 @@
         if (possessive) continue;
         for(;;)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM46);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM46);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           if (eptr-- == pp) break;        /* Stop if tried at original pos */
           BACKCHAR(eptr);
@@ -5484,7 +5476,7 @@
         if (possessive) continue;
         while (eptr >= pp)
           {
-          RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM47);
+          RMATCH(eptr, ecode, offset_top, md, eptrb, 0, RM47);
           if (rrc != MATCH_NOMATCH) RRETURN(rrc);
           eptr--;
           if (ctype == OP_ANYNL && eptr > pp  && *eptr == '\n' && 
@@ -5556,7 +5548,6 @@
 #undef ecode
 #undef mstart
 #undef offset_top
-#undef ims
 #undef eptrb
 #undef flags


@@ -5574,8 +5565,6 @@
#undef condition
#undef prev_is_word

-#undef original_ims
-
#undef ctype
#undef length
#undef max
@@ -5637,7 +5626,6 @@
int req_byte = -1;
int req_byte2 = -1;
int newline;
-unsigned long int ims;
BOOL using_temporary_offsets = FALSE;
BOOL anchored;
BOOL startline;
@@ -5854,12 +5842,6 @@
}
#endif

-/* The ims options can vary during the matching as a result of the presence
-of (?ims) items in the pattern. They are kept in a local variable so that
-restoring at the exit of a group is easy. */
-
-ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
-
 /* If the expression has got more back references than the offsets supplied can
 hold, we get a temporary chunk of working store to use during the matching.
 Otherwise, we can use the vector supplied, rounding down its size to a multiple
@@ -6138,7 +6120,7 @@
   md->start_match_ptr = start_match;
   md->start_used_ptr = start_match;
   md->match_call_count = 0;
-  rc = match(start_match, md->start_code, start_match, NULL, 2, md, ims, NULL,
+  rc = match(start_match, md->start_code, start_match, NULL, 2, md, NULL,
     0, 0);
   if (md->hitend && start_partial == NULL) start_partial = md->start_used_ptr;



Modified: code/trunk/pcre_internal.h
===================================================================
--- code/trunk/pcre_internal.h    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/pcre_internal.h    2011-05-25 08:29:03 UTC (rev 602)
@@ -1299,6 +1299,7 @@
   OP_WHITESPACE,         /*  9 \s */
   OP_NOT_WORDCHAR,       /* 10 \W */
   OP_WORDCHAR,           /* 11 \w */
+
   OP_ANY,            /* 12 Match any character except newline */
   OP_ALLANY,         /* 13 Match any character */
   OP_ANYBYTE,        /* 14 Match any byte (\C); different to OP_ANY for UTF-8 */
@@ -1313,141 +1314,194 @@
   OP_EODN,           /* 23 End of data or \n at end of data: \Z. */
   OP_EOD,            /* 24 End of data: \z */


-  OP_OPT,            /* 25 Set runtime options */
-  OP_CIRC,           /* 26 Start of line - varies with multiline switch */
-  OP_DOLL,           /* 27 End of line - varies with multiline switch */
-  OP_CHAR,           /* 28 Match one character, casefully */
-  OP_CHARNC,         /* 29 Match one character, caselessly */
-  OP_NOT,            /* 30 Match one character, not the following one */
+  OP_CIRC,           /* 25 Start of line - not multiline */
+  OP_CIRCM,          /* 26 Start of line - multiline */
+  OP_DOLL,           /* 27 End of line - not multiline */
+  OP_DOLLM,          /* 28 End of line - multiline */
+  OP_CHAR,           /* 29 Match one character, casefully */
+  OP_CHARI,          /* 30 Match one character, caselessly */
+  OP_NOT,            /* 31 Match one character, not the given one, casefully */
+  OP_NOTI,           /* 32 Match one character, not the given one, caselessly */


-  OP_STAR,           /* 31 The maximizing and minimizing versions of */
-  OP_MINSTAR,        /* 32 these six opcodes must come in pairs, with */
-  OP_PLUS,           /* 33 the minimizing one second. */
-  OP_MINPLUS,        /* 34 This first set applies to single characters.*/
-  OP_QUERY,          /* 35 */
-  OP_MINQUERY,       /* 36 */
+  /* The following sets of 13 opcodes must always be kept in step because
+  the offset from the first one is used to generate the others. */
+  
+  /**** Single characters, caseful, must precede the caseless ones ****/


-  OP_UPTO,           /* 37 From 0 to n matches */
-  OP_MINUPTO,        /* 38 */
-  OP_EXACT,          /* 39 Exactly n matches */
+  OP_STAR,           /* 33 The maximizing and minimizing versions of */
+  OP_MINSTAR,        /* 34 these six opcodes must come in pairs, with */
+  OP_PLUS,           /* 35 the minimizing one second. */
+  OP_MINPLUS,        /* 36 */
+  OP_QUERY,          /* 37 */
+  OP_MINQUERY,       /* 38 */


-  OP_POSSTAR,        /* 40 Possessified star */
-  OP_POSPLUS,        /* 41 Possessified plus */
-  OP_POSQUERY,       /* 42 Posesssified query */
-  OP_POSUPTO,        /* 43 Possessified upto */
+  OP_UPTO,           /* 39 From 0 to n matches of one character, caseful*/
+  OP_MINUPTO,        /* 40 */
+  OP_EXACT,          /* 41 Exactly n matches */


-  OP_NOTSTAR,        /* 44 The maximizing and minimizing versions of */
-  OP_NOTMINSTAR,     /* 45 these six opcodes must come in pairs, with */
-  OP_NOTPLUS,        /* 46 the minimizing one second. They must be in */
-  OP_NOTMINPLUS,     /* 47 exactly the same order as those above. */
-  OP_NOTQUERY,       /* 48 This set applies to "not" single characters. */
-  OP_NOTMINQUERY,    /* 49 */
+  OP_POSSTAR,        /* 42 Possessified star, caseful */
+  OP_POSPLUS,        /* 43 Possessified plus, caseful */
+  OP_POSQUERY,       /* 44 Posesssified query, caseful */
+  OP_POSUPTO,        /* 45 Possessified upto, caseful */


-  OP_NOTUPTO,        /* 50 From 0 to n matches */
-  OP_NOTMINUPTO,     /* 51 */
-  OP_NOTEXACT,       /* 52 Exactly n matches */
+  /**** Single characters, caseless, must follow the caseful ones */
+   
+  OP_STARI,          /* 46 */
+  OP_MINSTARI,       /* 47 */
+  OP_PLUSI,          /* 48 */
+  OP_MINPLUSI,       /* 49 */
+  OP_QUERYI,         /* 50 */
+  OP_MINQUERYI,      /* 51 */


-  OP_NOTPOSSTAR,     /* 53 Possessified versions */
-  OP_NOTPOSPLUS,     /* 54 */
-  OP_NOTPOSQUERY,    /* 55 */
-  OP_NOTPOSUPTO,     /* 56 */
+  OP_UPTOI,          /* 52 From 0 to n matches of one character, caseless */
+  OP_MINUPTOI,       /* 53 */
+  OP_EXACTI,         /* 54 */


-  OP_TYPESTAR,       /* 57 The maximizing and minimizing versions of */
-  OP_TYPEMINSTAR,    /* 58 these six opcodes must come in pairs, with */
-  OP_TYPEPLUS,       /* 59 the minimizing one second. These codes must */
-  OP_TYPEMINPLUS,    /* 60 be in exactly the same order as those above. */
-  OP_TYPEQUERY,      /* 61 This set applies to character types such as \d */
-  OP_TYPEMINQUERY,   /* 62 */
+  OP_POSSTARI,       /* 55 Possessified star, caseless */
+  OP_POSPLUSI,       /* 56 Possessified plus, caseless */
+  OP_POSQUERYI,      /* 57 Posesssified query, caseless */
+  OP_POSUPTOI,       /* 58 Possessified upto, caseless */


-  OP_TYPEUPTO,       /* 63 From 0 to n matches */
-  OP_TYPEMINUPTO,    /* 64 */
-  OP_TYPEEXACT,      /* 65 Exactly n matches */
+  /**** The negated ones must follow the non-negated ones, and match them ****/
+  /**** Negated single character, caseful; must precede the caseless ones ****/


-  OP_TYPEPOSSTAR,    /* 66 Possessified versions */
-  OP_TYPEPOSPLUS,    /* 67 */
-  OP_TYPEPOSQUERY,   /* 68 */
-  OP_TYPEPOSUPTO,    /* 69 */
+  OP_NOTSTAR,        /* 59 The maximizing and minimizing versions of */
+  OP_NOTMINSTAR,     /* 60 these six opcodes must come in pairs, with */
+  OP_NOTPLUS,        /* 61 the minimizing one second. They must be in */
+  OP_NOTMINPLUS,     /* 62 exactly the same order as those above. */
+  OP_NOTQUERY,       /* 63 */
+  OP_NOTMINQUERY,    /* 64 */


-  OP_CRSTAR,         /* 70 The maximizing and minimizing versions of */
-  OP_CRMINSTAR,      /* 71 all these opcodes must come in pairs, with */
-  OP_CRPLUS,         /* 72 the minimizing one second. These codes must */
-  OP_CRMINPLUS,      /* 73 be in exactly the same order as those above. */
-  OP_CRQUERY,        /* 74 These are for character classes and back refs */
-  OP_CRMINQUERY,     /* 75 */
-  OP_CRRANGE,        /* 76 These are different to the three sets above. */
-  OP_CRMINRANGE,     /* 77 */
+  OP_NOTUPTO,        /* 65 From 0 to n matches, caseful */
+  OP_NOTMINUPTO,     /* 66 */
+  OP_NOTEXACT,       /* 67 Exactly n matches */


-  OP_CLASS,          /* 78 Match a character class, chars < 256 only */
-  OP_NCLASS,         /* 79 Same, but the bitmap was created from a negative
-                           class - the difference is relevant only when a UTF-8
-                           character > 255 is encountered. */
+  OP_NOTPOSSTAR,     /* 68 Possessified versions, caseful */
+  OP_NOTPOSPLUS,     /* 69 */
+  OP_NOTPOSQUERY,    /* 70 */
+  OP_NOTPOSUPTO,     /* 71 */


-  OP_XCLASS,         /* 80 Extended class for handling UTF-8 chars within the
-                           class. This does both positive and negative. */
+  /**** Negated single character, caseless; must follow the caseful ones ****/
+   
+  OP_NOTSTARI,       /* 72 */
+  OP_NOTMINSTARI,    /* 73 */
+  OP_NOTPLUSI,       /* 74 */
+  OP_NOTMINPLUSI,    /* 75 */
+  OP_NOTQUERYI,      /* 76 */
+  OP_NOTMINQUERYI,   /* 77 */


-  OP_REF,            /* 81 Match a back reference */
-  OP_RECURSE,        /* 82 Match a numbered subpattern (possibly recursive) */
-  OP_CALLOUT,        /* 83 Call out to external function if provided */
+  OP_NOTUPTOI,       /* 78 From 0 to n matches, caseless */
+  OP_NOTMINUPTOI,    /* 79 */
+  OP_NOTEXACTI,      /* 80 Exactly n matches */


-  OP_ALT,            /* 84 Start of alternation */
-  OP_KET,            /* 85 End of group that doesn't have an unbounded repeat */
-  OP_KETRMAX,        /* 86 These two must remain together and in this */
-  OP_KETRMIN,        /* 87 order. They are for groups the repeat for ever. */
+  OP_NOTPOSSTARI,    /* 81 Possessified versions, caseless */
+  OP_NOTPOSPLUSI,    /* 82 */
+  OP_NOTPOSQUERYI,   /* 83 */
+  OP_NOTPOSUPTOI,    /* 84 */


+  /**** Character types ****/
+   
+  OP_TYPESTAR,       /* 85 The maximizing and minimizing versions of */
+  OP_TYPEMINSTAR,    /* 86 these six opcodes must come in pairs, with */
+  OP_TYPEPLUS,       /* 87 the minimizing one second. These codes must */
+  OP_TYPEMINPLUS,    /* 88 be in exactly the same order as those above. */
+  OP_TYPEQUERY,      /* 89 */
+  OP_TYPEMINQUERY,   /* 90 */
+
+  OP_TYPEUPTO,       /* 91 From 0 to n matches */
+  OP_TYPEMINUPTO,    /* 92 */
+  OP_TYPEEXACT,      /* 93 Exactly n matches */
+
+  OP_TYPEPOSSTAR,    /* 94 Possessified versions */
+  OP_TYPEPOSPLUS,    /* 95 */
+  OP_TYPEPOSQUERY,   /* 96 */
+  OP_TYPEPOSUPTO,    /* 97 */
+
+  /* These are used for character classes and back references; only the
+  first six are the same as the sets above. */ 
+
+  OP_CRSTAR,         /* 98 The maximizing and minimizing versions of */
+  OP_CRMINSTAR,      /* 99 all these opcodes must come in pairs, with */
+  OP_CRPLUS,         /* 100 the minimizing one second. These codes must */
+  OP_CRMINPLUS,      /* 101 be in exactly the same order as those above. */
+  OP_CRQUERY,        /* 102 */
+  OP_CRMINQUERY,     /* 103 */
+
+  OP_CRRANGE,        /* 104 These are different to the three sets above. */
+  OP_CRMINRANGE,     /* 105 */
+
+  /* End of quantifier opcodes */
+
+  OP_CLASS,          /* 106 Match a character class, chars < 256 only */
+  OP_NCLASS,         /* 107 Same, but the bitmap was created from a negative
+                              class - the difference is relevant only when a
+                              UTF-8 character > 255 is encountered. */
+  OP_XCLASS,         /* 108 Extended class for handling UTF-8 chars within the
+                              class. This does both positive and negative. */
+  OP_REF,            /* 109 Match a back reference, casefully */
+  OP_REFI,           /* 110 Match a back reference, caselessly */
+  OP_RECURSE,        /* 111 Match a numbered subpattern (possibly recursive) */
+  OP_CALLOUT,        /* 112 Call out to external function if provided */
+
+  OP_ALT,            /* 113 Start of alternation */
+  OP_KET,            /* 114 End of group that doesn't have an unbounded repeat */
+  OP_KETRMAX,        /* 115 These two must remain together and in this */
+  OP_KETRMIN,        /* 116 order. They are for groups the repeat for ever. */
+
   /* The assertions must come before BRA, CBRA, ONCE, and COND.*/


-  OP_ASSERT,         /* 88 Positive lookahead */
-  OP_ASSERT_NOT,     /* 89 Negative lookahead */
-  OP_ASSERTBACK,     /* 90 Positive lookbehind */
-  OP_ASSERTBACK_NOT, /* 91 Negative lookbehind */
-  OP_REVERSE,        /* 92 Move pointer back - used in lookbehind assertions */
+  OP_ASSERT,         /* 117 Positive lookahead */
+  OP_ASSERT_NOT,     /* 118 Negative lookahead */
+  OP_ASSERTBACK,     /* 119 Positive lookbehind */
+  OP_ASSERTBACK_NOT, /* 120 Negative lookbehind */
+  OP_REVERSE,        /* 121 Move pointer back - used in lookbehind assertions */


/* ONCE, BRA, CBRA, and COND must come after the assertions, with ONCE first,
as there's a test for >= ONCE for a subpattern that isn't an assertion. */

-  OP_ONCE,           /* 93 Atomic group */
-  OP_BRA,            /* 94 Start of non-capturing bracket */
-  OP_CBRA,           /* 95 Start of capturing bracket */
-  OP_COND,           /* 96 Conditional group */
+  OP_ONCE,           /* 122 Atomic group */
+  OP_BRA,            /* 123 Start of non-capturing bracket */
+  OP_CBRA,           /* 124 Start of capturing bracket */
+  OP_COND,           /* 125 Conditional group */


/* These three must follow the previous three, in the same order. There's a
check for >= SBRA to distinguish the two sets. */

-  OP_SBRA,           /* 97 Start of non-capturing bracket, check empty  */
-  OP_SCBRA,          /* 98 Start of capturing bracket, check empty */
-  OP_SCOND,          /* 99 Conditional group, check empty */
+  OP_SBRA,           /* 126 Start of non-capturing bracket, check empty  */
+  OP_SCBRA,          /* 127 Start of capturing bracket, check empty */
+  OP_SCOND,          /* 128 Conditional group, check empty */


/* The next two pairs must (respectively) be kept together. */

-  OP_CREF,           /* 100 Used to hold a capture number as condition */
-  OP_NCREF,          /* 101 Same, but generated by a name reference*/
-  OP_RREF,           /* 102 Used to hold a recursion number as condition */
-  OP_NRREF,          /* 103 Same, but generated by a name reference*/
-  OP_DEF,            /* 104 The DEFINE condition */
+  OP_CREF,           /* 129 Used to hold a capture number as condition */
+  OP_NCREF,          /* 130 Same, but generated by a name reference*/
+  OP_RREF,           /* 131 Used to hold a recursion number as condition */
+  OP_NRREF,          /* 132 Same, but generated by a name reference*/
+  OP_DEF,            /* 133 The DEFINE condition */


-  OP_BRAZERO,        /* 105 These two must remain together and in this */
-  OP_BRAMINZERO,     /* 106 order. */
+  OP_BRAZERO,        /* 134 These two must remain together and in this */
+  OP_BRAMINZERO,     /* 135 order. */


/* These are backtracking control verbs */

-  OP_MARK,           /* 107 always has an argument */
-  OP_PRUNE,          /* 108 */
-  OP_PRUNE_ARG,      /* 109 same, but with argument */
-  OP_SKIP,           /* 110 */
-  OP_SKIP_ARG,       /* 111 same, but with argument */
-  OP_THEN,           /* 112 */
-  OP_THEN_ARG,       /* 113 same, but with argument */
-  OP_COMMIT,         /* 114 */
+  OP_MARK,           /* 136 always has an argument */
+  OP_PRUNE,          /* 137 */
+  OP_PRUNE_ARG,      /* 138 same, but with argument */
+  OP_SKIP,           /* 139 */
+  OP_SKIP_ARG,       /* 140 same, but with argument */
+  OP_THEN,           /* 141 */
+  OP_THEN_ARG,       /* 142 same, but with argument */
+  OP_COMMIT,         /* 143 */


/* These are forced failure and success verbs */

-  OP_FAIL,           /* 115 */
-  OP_ACCEPT,         /* 116 */
-  OP_CLOSE,          /* 117 Used before OP_ACCEPT to close open captures */
+  OP_FAIL,           /* 144 */
+  OP_ACCEPT,         /* 145 */
+  OP_CLOSE,          /* 146 Used before OP_ACCEPT to close open captures */


/* This is used to skip a subpattern with a {0} quantifier */

-  OP_SKIPZERO,       /* 118 */
+  OP_SKIPZERO,       /* 147 */


/* This is not an opcode, but is used to check that tables indexed by opcode
are the correct length, in order to catch updating errors - there have been
@@ -1462,22 +1516,33 @@


/* This macro defines textual names for all the opcodes. These are used only
-for debugging. The macro is referenced only in pcre_printint.c. */
+for debugging, and some of them are only partial names. The macro is referenced
+only in pcre_printint.c, which fills out the full names in many cases (and in
+some cases doesn't actually use these names at all). */

 #define OP_NAME_LIST \
   "End", "\\A", "\\G", "\\K", "\\B", "\\b", "\\D", "\\d",         \
   "\\S", "\\s", "\\W", "\\w", "Any", "AllAny", "Anybyte",         \
   "notprop", "prop", "\\R", "\\H", "\\h", "\\V", "\\v",           \
   "extuni",  "\\Z", "\\z",                                        \
-  "Opt", "^", "$", "char", "charnc", "not",                       \
-  "*", "*?", "+", "+?", "?", "??", "{", "{", "{",                 \
+  "^", "^", "$", "$", "char", "chari", "not", "noti",             \
+  "*", "*?", "+", "+?", "?", "??",                                \
+  "{", "{", "{",                                                  \
   "*+","++", "?+", "{",                                           \
-  "*", "*?", "+", "+?", "?", "??", "{", "{", "{",                 \
+  "*", "*?", "+", "+?", "?", "??",                                \
+  "{", "{", "{",                                                  \
   "*+","++", "?+", "{",                                           \
+  "*", "*?", "+", "+?", "?", "??",                                \
+  "{", "{", "{",                                                  \
+  "*+","++", "?+", "{",                                           \
+  "*", "*?", "+", "+?", "?", "??",                                \
+  "{", "{", "{",                                                  \
+  "*+","++", "?+", "{",                                           \
   "*", "*?", "+", "+?", "?", "??", "{", "{", "{",                 \
   "*+","++", "?+", "{",                                           \
   "*", "*?", "+", "+?", "?", "??", "{", "{",                      \
-  "class", "nclass", "xclass", "Ref", "Recurse", "Callout",       \
+  "class", "nclass", "xclass", "Ref", "Refi",                     \
+  "Recurse", "Callout",                                           \
   "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not",     \
   "AssertB", "AssertB not", "Reverse",                            \
   "Once", "Bra", "CBra", "Cond", "SBra", "SCBra", "SCond",        \
@@ -1505,18 +1570,25 @@
   3, 3,                          /* \P, \p                                 */ \
   1, 1, 1, 1, 1,                 /* \R, \H, \h, \V, \v                     */ \
   1,                             /* \X                                     */ \
-  1, 1, 2, 1, 1,                 /* \Z, \z, Opt, ^, $                      */ \
+  1, 1, 1, 1, 1, 1,              /* \Z, \z, ^, ^M, $, $M                   */ \
   2,                             /* Char  - the minimum length             */ \
-  2,                             /* Charnc  - the minimum length           */ \
+  2,                             /* Chari  - the minimum length            */ \
   2,                             /* not                                    */ \
-  /* Positive single-char repeats                            ** These are  */ \
-  2, 2, 2, 2, 2, 2,              /* *, *?, +, +?, ?, ??      ** minima in  */ \
-  4, 4, 4,                       /* upto, minupto, exact     ** UTF-8 mode */ \
+  2,                             /* noti                                   */ \
+  /* Positive single-char repeats                             ** These are */ \
+  2, 2, 2, 2, 2, 2,              /* *, *?, +, +?, ?, ??       ** minima in */ \
+  4, 4, 4,                       /* upto, minupto, exact      ** mode      */ \
   2, 2, 2, 4,                    /* *+, ++, ?+, upto+                      */ \
+  2, 2, 2, 2, 2, 2,              /* *I, *?I, +I, +?I, ?I, ??I ** UTF-8     */ \
+  4, 4, 4,                       /* upto I, minupto I, exact I             */ \
+  2, 2, 2, 4,                    /* *+I, ++I, ?+I, upto+I                  */ \
   /* Negative single-char repeats - only for chars < 256                   */ \
   2, 2, 2, 2, 2, 2,              /* NOT *, *?, +, +?, ?, ??                */ \
   4, 4, 4,                       /* NOT upto, minupto, exact               */ \
-  2, 2, 2, 4,                    /* Possessive *, +, ?, upto               */ \
+  2, 2, 2, 4,                    /* Possessive NOT *, +, ?, upto           */ \
+  2, 2, 2, 2, 2, 2,              /* NOT *I, *?I, +I, +?I, ?I, ??I          */ \
+  4, 4, 4,                       /* NOT upto I, minupto I, exact I         */ \
+  2, 2, 2, 4,                    /* Possessive NOT *I, +I, ?I, upto I      */ \
   /* Positive type repeats                                                 */ \
   2, 2, 2, 2, 2, 2,              /* Type *, *?, +, +?, ?, ??               */ \
   4, 4, 4,                       /* Type upto, minupto, exact              */ \
@@ -1528,6 +1600,7 @@
  33,                             /* NCLASS                                 */ \
   0,                             /* XCLASS - variable length               */ \
   3,                             /* REF                                    */ \
+  3,                             /* REFI                                   */ \
   1+LINK_SIZE,                   /* RECURSE                                */ \
   2+2*LINK_SIZE,                 /* CALLOUT                                */ \
   1+LINK_SIZE,                   /* Alt                                    */ \
@@ -1553,9 +1626,8 @@
   3, 1, 3,                       /* MARK, PRUNE, PRUNE_ARG                 */ \
   1, 3,                          /* SKIP, SKIP_ARG                         */ \
   1+LINK_SIZE, 3+LINK_SIZE,      /* THEN, THEN_ARG                         */ \
-  1, 1, 1, 3, 1                  /* COMMIT, FAIL, ACCEPT, CLOSE, SKIPZERO  */
+  1, 1, 1, 3, 1                  /* COMMIT, FAIL, ACCEPT, CLOSE, SKIPZERO  */ \


-
/* A magic value for OP_RREF and OP_NRREF to indicate the "any recursion"
condition. */


Modified: code/trunk/pcre_printint.src
===================================================================
--- code/trunk/pcre_printint.src    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/pcre_printint.src    2011-05-25 08:29:03 UTC (rev 602)
@@ -180,6 +180,7 @@
 for(;;)
   {
   uschar *ccode;
+  const char *flag = "  "; 
   int c;
   int extra = 0;


@@ -214,10 +215,6 @@
     fprintf(f, "------------------------------------------------------------------\n");
     return;


-    case OP_OPT:
-    fprintf(f, " %.2x %s", code[1], OP_names[*code]);
-    break;
-
     case OP_CHAR:
     fprintf(f, "    ");
     do
@@ -229,14 +226,14 @@
     fprintf(f, "\n");
     continue;


-    case OP_CHARNC:
-    fprintf(f, " NC ");
+    case OP_CHARI:
+    fprintf(f, " /i ");
     do
       {
       code++;
       code += 1 + print_char(f, code, utf8);
       }
-    while (*code == OP_CHARNC);
+    while (*code == OP_CHARI);
     fprintf(f, "\n");
     continue;


@@ -295,6 +292,17 @@
     fprintf(f, "    Cond def");
     break;


+    case OP_STARI:
+    case OP_MINSTARI:
+    case OP_POSSTARI:
+    case OP_PLUSI:
+    case OP_MINPLUSI:
+    case OP_POSPLUSI:
+    case OP_QUERYI:
+    case OP_MINQUERYI:
+    case OP_POSQUERYI:
+    flag = "/i";
+    /* Fall through */  
     case OP_STAR:
     case OP_MINSTAR:
     case OP_POSSTAR:
@@ -313,7 +321,7 @@
     case OP_TYPEQUERY:
     case OP_TYPEMINQUERY:
     case OP_TYPEPOSQUERY:
-    fprintf(f, "    ");
+    fprintf(f, " %s ", flag);
     if (*code >= OP_TYPESTAR)
       {
       fprintf(f, "%s", OP_names[code[1]]);
@@ -327,17 +335,23 @@
     fprintf(f, "%s", OP_names[*code]);
     break;


+    case OP_EXACTI:
+    case OP_UPTOI:
+    case OP_MINUPTOI:
+    case OP_POSUPTOI:
+    flag = "/i";
+    /* Fall through */  
     case OP_EXACT:
     case OP_UPTO:
     case OP_MINUPTO:
     case OP_POSUPTO:
-    fprintf(f, "    ");
+    fprintf(f, " %s ", flag);
     extra = print_char(f, code+3, utf8);
     fprintf(f, "{");
-    if (*code != OP_EXACT) fprintf(f, "0,");
+    if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");
     fprintf(f, "%d}", GET2(code,1));
-    if (*code == OP_MINUPTO) fprintf(f, "?");
-      else if (*code == OP_POSUPTO) fprintf(f, "+");
+    if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?");
+      else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+");
     break;


     case OP_TYPEEXACT:
@@ -357,12 +371,27 @@
       else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+");
     break;


+    case OP_NOTI:
+    flag = "/i";
+    /* Fall through */  
     case OP_NOT:
     c = code[1];
-    if (PRINTABLE(c)) fprintf(f, "    [^%c]", c);
-      else fprintf(f, "    [^\\x%02x]", c);
+    if (PRINTABLE(c)) fprintf(f, " %s [^%c]", flag, c);
+      else fprintf(f, " %s [^\\x%02x]", flag, c);
     break;


+    case OP_NOTSTARI:
+    case OP_NOTMINSTARI:
+    case OP_NOTPOSSTARI:
+    case OP_NOTPLUSI:
+    case OP_NOTMINPLUSI:
+    case OP_NOTPOSPLUSI:
+    case OP_NOTQUERYI:
+    case OP_NOTMINQUERYI:
+    case OP_NOTPOSQUERYI:
+    flag = "/i";
+    /* Fall through */  
+
     case OP_NOTSTAR:
     case OP_NOTMINSTAR:
     case OP_NOTPOSSTAR:
@@ -373,22 +402,30 @@
     case OP_NOTMINQUERY:
     case OP_NOTPOSQUERY:
     c = code[1];
-    if (PRINTABLE(c)) fprintf(f, "    [^%c]", c);
-      else fprintf(f, "    [^\\x%02x]", c);
+    if (PRINTABLE(c)) fprintf(f, " %s [^%c]", flag, c);
+      else fprintf(f, " %s [^\\x%02x]", flag, c);
     fprintf(f, "%s", OP_names[*code]);
     break;


+    case OP_NOTEXACTI:
+    case OP_NOTUPTOI:
+    case OP_NOTMINUPTOI:
+    case OP_NOTPOSUPTOI:
+    flag = "/i";
+    /* Fall through */  
+
     case OP_NOTEXACT:
     case OP_NOTUPTO:
     case OP_NOTMINUPTO:
     case OP_NOTPOSUPTO:
     c = code[3];
-    if (PRINTABLE(c)) fprintf(f, "    [^%c]{", c);
-      else fprintf(f, "    [^\\x%02x]{", c);
-    if (*code != OP_NOTEXACT) fprintf(f, "0,");
+    if (PRINTABLE(c)) fprintf(f, " %s [^%c]{", flag, c);
+      else fprintf(f, " %s [^\\x%02x]{", flag, c);
+    if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");
     fprintf(f, "%d}", GET2(code,1));
-    if (*code == OP_NOTMINUPTO) fprintf(f, "?");
-      else if (*code == OP_NOTPOSUPTO) fprintf(f, "+");
+    if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?");
+      else 
+    if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+");
     break;


     case OP_RECURSE:
@@ -397,8 +434,11 @@
     fprintf(f, "%s", OP_names[*code]);
     break;


+    case OP_REFI:
+    flag = "/i";
+    /* Fall through */  
     case OP_REF:
-    fprintf(f, "    \\%d", GET2(code,1));
+    fprintf(f, " %s \\%d", flag, GET2(code,1));
     ccode = code + _pcre_OP_lengths[*code];
     goto CLASS_REF_REPEAT;


@@ -556,11 +596,16 @@
       fprintf(f, "    %s %s", OP_names[*code], code + 2 + LINK_SIZE);
     extra += code[1+LINK_SIZE];
     break;
+    
+    case OP_CIRCM:
+    case OP_DOLLM:
+    flag = "/m";
+    /* Fall through */    
+    
+    /* Anything else is just an item with no data, but possibly a flag. */


-    /* Anything else is just an item with no data*/
-
     default:
-    fprintf(f, "    %s", OP_names[*code]);
+    fprintf(f, " %s %s", flag, OP_names[*code]);
     break;
     }



Modified: code/trunk/pcre_study.c
===================================================================
--- code/trunk/pcre_study.c    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/pcre_study.c    2011-05-25 08:29:03 UTC (rev 602)
@@ -160,14 +160,15 @@
     case OP_RREF:
     case OP_NRREF:
     case OP_DEF:
-    case OP_OPT:
     case OP_CALLOUT:
     case OP_SOD:
     case OP_SOM:
     case OP_EOD:
     case OP_EODN:
     case OP_CIRC:
+    case OP_CIRCM:
     case OP_DOLL:
+    case OP_DOLLM:
     case OP_NOT_WORD_BOUNDARY:
     case OP_WORD_BOUNDARY:
     cc += _pcre_OP_lengths[*cc];
@@ -186,8 +187,9 @@
     /* Handle literal characters and + repetitions */


     case OP_CHAR:
-    case OP_CHARNC:
+    case OP_CHARI:
     case OP_NOT:
+    case OP_NOTI:
     case OP_PLUS:
     case OP_MINPLUS:
     case OP_POSPLUS:
@@ -337,6 +339,7 @@
     that case we must set the minimum length to zero. */


     case OP_REF:
+    case OP_REFI:
     if ((options & PCRE_JAVASCRIPT_COMPAT) == 0)
       {
       ce = cs = (uschar *)_pcre_find_bracket(startcode, utf8, GET2(cc, 1));
@@ -391,23 +394,50 @@


     /* Anything else does not or need not match a character. We can get the
     item's length from the table, but for those that can match zero occurrences
-    of a character, we must take special action for UTF-8 characters. */
+    of a character, we must take special action for UTF-8 characters. As it
+    happens, the "NOT" versions of these opcodes are used at present only for
+    ASCII characters, so they could be omitted from this list. However, in
+    future that may change, so we leave them in this special case. */


     case OP_UPTO:
+    case OP_UPTOI:
     case OP_NOTUPTO:
+    case OP_NOTUPTOI:
     case OP_MINUPTO:
+    case OP_MINUPTOI:
     case OP_NOTMINUPTO:
+    case OP_NOTMINUPTOI:
     case OP_POSUPTO:
+    case OP_POSUPTOI:
+    case OP_NOTPOSUPTO:
+    case OP_NOTPOSUPTOI:
+
     case OP_STAR:
+    case OP_STARI:
+    case OP_NOTSTAR:
+    case OP_NOTSTARI:
     case OP_MINSTAR:
+    case OP_MINSTARI:
     case OP_NOTMINSTAR:
+    case OP_NOTMINSTARI:
     case OP_POSSTAR:
+    case OP_POSSTARI:
     case OP_NOTPOSSTAR:
+    case OP_NOTPOSSTARI:
+
     case OP_QUERY:
+    case OP_QUERYI:
+    case OP_NOTQUERY:
+    case OP_NOTQUERYI:
     case OP_MINQUERY:
+    case OP_MINQUERYI:
     case OP_NOTMINQUERY:
+    case OP_NOTMINQUERYI:
     case OP_POSQUERY:
+    case OP_POSQUERYI:
     case OP_NOTPOSQUERY:
+    case OP_NOTPOSQUERYI:
+
     cc += _pcre_OP_lengths[op];
 #ifdef SUPPORT_UTF8
     if (utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
@@ -679,13 +709,6 @@
       tcode += 1 + LINK_SIZE;
       break;


-      /* Skip over an option setting, changing the caseless flag */
-
-      case OP_OPT:
-      caseless = (tcode[1] & PCRE_CASELESS) != 0;
-      tcode += 2;
-      break;
-
       /* BRAZERO does the bracket, but carries on. */


       case OP_BRAZERO:
@@ -720,6 +743,15 @@
       tcode = set_table_bit(start_bits, tcode + 1, caseless, cd, utf8);
       break;


+      case OP_STARI:
+      case OP_MINSTARI:
+      case OP_POSSTARI:
+      case OP_QUERYI:
+      case OP_MINQUERYI:
+      case OP_POSQUERYI:
+      tcode = set_table_bit(start_bits, tcode + 1, TRUE, cd, utf8);
+      break;
+
       /* Single-char upto sets the bit and tries the next */


       case OP_UPTO:
@@ -728,13 +760,18 @@
       tcode = set_table_bit(start_bits, tcode + 3, caseless, cd, utf8);
       break;


+      case OP_UPTOI:
+      case OP_MINUPTOI:
+      case OP_POSUPTOI:
+      tcode = set_table_bit(start_bits, tcode + 3, TRUE, cd, utf8);
+      break;
+
       /* At least one single char sets the bit and stops */


-      case OP_EXACT:       /* Fall through */
+      case OP_EXACT:
       tcode += 2;
-
+      /* Fall through */
       case OP_CHAR:
-      case OP_CHARNC:
       case OP_PLUS:
       case OP_MINPLUS:
       case OP_POSPLUS:
@@ -742,6 +779,14 @@
       try_next = FALSE;
       break;


+      case OP_CHARI:
+      case OP_PLUSI:
+      case OP_MINPLUSI:
+      case OP_POSPLUSI:
+      (void)set_table_bit(start_bits, tcode + 1, TRUE, cd, utf8);
+      try_next = FALSE;
+      break;
+
       /* Special spacing and line-terminating items. These recognize specific
       lists of characters. The difference between VSPACE and ANYNL is that the
       latter can match the two-character CRLF sequence, but that is not


Modified: code/trunk/testdata/testinput1
===================================================================
--- code/trunk/testdata/testinput1    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/testdata/testinput1    2011-05-25 08:29:03 UTC (rev 602)
@@ -4085,4 +4085,49 @@
 /(abc)\1/
    abc


+/[^a]*/i
+    12abc
+    12ABC
+
+/[^a]*+/i
+    12abc
+    12ABC
+
+/[^a]*?X/i
+    ** Failers
+    12abc
+    12ABC
+    
+/[^a]+?X/i   
+    ** Failers
+    12abc
+    12ABC
+
+/[^a]?X/i
+    12aXbcX
+    12AXBCX
+    BCX 
+
+/[^a]??X/i
+    12aXbcX
+    12AXBCX
+    BCX
+    
+/[^a]?+X/i
+    12aXbcX
+    12AXBCX
+    BCX 
+
+/[^a]{2,3}/i
+    abcdef
+    ABCDEF  
+
+/[^a]{2,3}?/i
+    abcdef
+    ABCDEF  
+
+/[^a]{2,3}+/i
+    abcdef
+    ABCDEF  
+
 /-- End of testinput1 --/


Modified: code/trunk/testdata/testinput11
===================================================================
--- code/trunk/testdata/testinput11    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/testdata/testinput11    2011-05-25 08:29:03 UTC (rev 602)
@@ -507,4 +507,13 @@
 /(?P<abn>(?P=abn)xxx|)+/
     xxx


+/(?i:([^b]))(?1)/
+    aa
+    aA     
+    ** Failers
+    ab
+    aB
+    Ba
+    ba
+
 /-- End of testinput11 --/


Modified: code/trunk/testdata/testinput2
===================================================================
--- code/trunk/testdata/testinput2    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/testdata/testinput2    2011-05-25 08:29:03 UTC (rev 602)
@@ -3589,4 +3589,8 @@


/-- --/

+/^abc$/BZ
+
+/^abc$/BZm
+
/-- End of testinput2 --/

Modified: code/trunk/testdata/testoutput1
===================================================================
--- code/trunk/testdata/testoutput1    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/testdata/testoutput1    2011-05-25 08:29:03 UTC (rev 602)
@@ -6674,4 +6674,74 @@
    abc
 No match


+/[^a]*/i
+    12abc
+ 0: 12
+    12ABC
+ 0: 12
+
+/[^a]*+/i
+    12abc
+ 0: 12
+    12ABC
+ 0: 12
+
+/[^a]*?X/i
+    ** Failers
+No match
+    12abc
+No match
+    12ABC
+No match
+    
+/[^a]+?X/i   
+    ** Failers
+No match
+    12abc
+No match
+    12ABC
+No match
+
+/[^a]?X/i
+    12aXbcX
+ 0: X
+    12AXBCX
+ 0: X
+    BCX 
+ 0: CX
+
+/[^a]??X/i
+    12aXbcX
+ 0: X
+    12AXBCX
+ 0: X
+    BCX
+ 0: CX
+    
+/[^a]?+X/i
+    12aXbcX
+ 0: cX
+    12AXBCX
+ 0: CX
+    BCX 
+ 0: CX
+
+/[^a]{2,3}/i
+    abcdef
+ 0: bcd
+    ABCDEF  
+ 0: BCD
+
+/[^a]{2,3}?/i
+    abcdef
+ 0: bc
+    ABCDEF  
+ 0: BC
+
+/[^a]{2,3}+/i
+    abcdef
+ 0: bcd
+    ABCDEF  
+ 0: BCD
+
 /-- End of testinput1 --/


Modified: code/trunk/testdata/testoutput10
===================================================================
--- code/trunk/testdata/testoutput10    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/testdata/testoutput10    2011-05-25 08:29:03 UTC (rev 602)
@@ -5,16 +5,14 @@
 is required for these tests. --/


 /((?i)b)/BM
-Memory allocation (code space): 21
+Memory allocation (code space): 17
 ------------------------------------------------------------------
-  0  17 Bra
-  3   9 CBra 1
-  8  01 Opt
- 10  NC b
- 12   9 Ket
- 15  00 Opt
- 17  17 Ket
- 20     End
+  0  13 Bra
+  3   7 CBra 1
+  8  /i b
+ 10   7 Ket
+ 13  13 Ket
+ 16     End
 ------------------------------------------------------------------


/(?s)(.*X|^B)/BM
@@ -33,21 +31,18 @@
------------------------------------------------------------------

 /(?s:.*X|^B)/BM
-Memory allocation (code space): 29
+Memory allocation (code space): 23
 ------------------------------------------------------------------
-  0  25 Bra
-  3   9 Bra
-  6  04 Opt
-  8     AllAny*
- 10     X
- 12   8 Alt
- 15  04 Opt
- 17     ^
- 18     B
- 20  17 Ket
- 23  00 Opt
- 25  25 Ket
- 28     End
+  0  19 Bra
+  3   7 Bra
+  6     AllAny*
+  8     X
+ 10   6 Alt
+ 13     ^
+ 14     B
+ 16  13 Ket
+ 19  19 Ket
+ 22     End
 ------------------------------------------------------------------


 /^[[:alnum:]]/BM
@@ -538,7 +533,7 @@
 Memory allocation (code space): 25
 ------------------------------------------------------------------
   0  21 Bra
-  3  NC A\x{391}\x{10427}\x{ff3a}\x{1fb0}
+  3  /i A\x{391}\x{10427}\x{ff3a}\x{1fb0}
  21  21 Ket
  24     End
 ------------------------------------------------------------------


Modified: code/trunk/testdata/testoutput11
===================================================================
--- code/trunk/testdata/testoutput11    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/testdata/testoutput11    2011-05-25 08:29:03 UTC (rev 602)
@@ -975,4 +975,23 @@
  0: 
  1: 


+/(?i:([^b]))(?1)/
+    aa
+ 0: aa
+ 1: a
+    aA     
+ 0: aA
+ 1: a
+    ** Failers
+ 0: **
+ 1: *
+    ab
+No match
+    aB
+No match
+    Ba
+No match
+    ba
+No match
+
 /-- End of testinput11 --/


Modified: code/trunk/testdata/testoutput12
===================================================================
--- code/trunk/testdata/testoutput12    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/testdata/testoutput12    2011-05-25 08:29:03 UTC (rev 602)
@@ -100,7 +100,7 @@
 /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8iDZ
 ------------------------------------------------------------------
         Bra
-     NC A\x{391}\x{10427}\x{ff3a}\x{1fb0}
+     /i A\x{391}\x{10427}\x{ff3a}\x{1fb0}
         Ket
         End
 ------------------------------------------------------------------
@@ -136,7 +136,7 @@
 /AB\x{1fb0}/8DZi
 ------------------------------------------------------------------
         Bra
-     NC AB\x{1fb0}
+     /i AB\x{1fb0}
         Ket
         End
 ------------------------------------------------------------------


Modified: code/trunk/testdata/testoutput2
===================================================================
--- code/trunk/testdata/testoutput2    2011-05-09 09:06:55 UTC (rev 601)
+++ code/trunk/testdata/testoutput2    2011-05-25 08:29:03 UTC (rev 602)
@@ -632,10 +632,8 @@
 ------------------------------------------------------------------
         Bra
         CBra 1
-     01 Opt
-     NC b
+     /i b
         Ket
-     00 Opt
         Ket
         End
 ------------------------------------------------------------------
@@ -1247,15 +1245,12 @@
 ------------------------------------------------------------------
         Bra
         Bra
-     04 Opt
         AllAny*
         X
         Alt
-     04 Opt
         ^
         B
         Ket
-     00 Opt
         Ket
         End
 ------------------------------------------------------------------
@@ -2764,8 +2759,7 @@
 ------------------------------------------------------------------
         Bra
         a
-     01 Opt
-     NC b
+     /i b
         Ket
         End
 ------------------------------------------------------------------
@@ -2787,10 +2781,8 @@
         Bra
         CBra 1
         a
-     01 Opt
-     NC b
+     /i b
         Ket
-     00 Opt
         Ket
         End
 ------------------------------------------------------------------
@@ -2812,7 +2804,7 @@
 /   (?i)abc/IxDZ
 ------------------------------------------------------------------
         Bra
-     NC abc
+     /i abc
         Ket
         End
 ------------------------------------------------------------------
@@ -2825,7 +2817,7 @@
   (?i)abc/IxDZ
 ------------------------------------------------------------------
         Bra
-     NC abc
+     /i abc
         Ket
         End
 ------------------------------------------------------------------
@@ -6674,8 +6666,8 @@
 ------------------------------------------------------------------
         Bra
         ^
-        a*
-     NC A
+     /i a*
+     /i A
         \d
         Ket
         End
@@ -7303,8 +7295,8 @@
 /[^a]+a/BZi
 ------------------------------------------------------------------
         Bra
-        [^A]++
-     NC a
+     /i [^A]++
+     /i a
         Ket
         End
 ------------------------------------------------------------------
@@ -7312,8 +7304,8 @@
 /[^a]+A/BZi
 ------------------------------------------------------------------
         Bra
-        [^A]++
-     NC A
+     /i [^A]++
+     /i A
         Ket
         End
 ------------------------------------------------------------------
@@ -10586,11 +10578,9 @@
 /(?i)a(?-i)b|c/BZ
 ------------------------------------------------------------------
         Bra
-     NC a
-     00 Opt
+     /i a
         b
         Alt
-     00 Opt
         c
         Ket
         End
@@ -10609,12 +10599,9 @@
 /(?i)a(?s)b|c/BZ
 ------------------------------------------------------------------
         Bra
-     NC a
-     05 Opt
-     NC b
+     /i ab
         Alt
-     05 Opt
-     NC c
+     /i c
         Ket
         End
 ------------------------------------------------------------------
@@ -10622,11 +10609,9 @@
 /(?i)a(?s-i)b|c/BZ
 ------------------------------------------------------------------
         Bra
-     NC a
-     04 Opt
+     /i a
         b
         Alt
-     04 Opt
         c
         Ket
         End
@@ -11351,4 +11336,24 @@


/-- --/

+/^abc$/BZ
+------------------------------------------------------------------
+        Bra
+        ^
+        abc
+        $
+        Ket
+        End
+------------------------------------------------------------------
+
+/^abc$/BZm
+------------------------------------------------------------------
+        Bra
+     /m ^
+        abc
+     /m $
+        Ket
+        End
+------------------------------------------------------------------
+
 /-- End of testinput2 --/