2007-11-24 Eric Seidel <eric@webkit.org>
[WebKit-https.git] / JavaScriptCore / pcre / pcre_compile.cpp
index 2835ec781c01292d851a58b11318cf838e563bba..94b815fe4936e7b67c8c21a8cfa51162f4dc4a06 100644 (file)
@@ -900,11 +900,11 @@ compile_branch(int options, int* brackets, uschar** codeptr,
     int zerofirstbyte = REQ_UNSET;
     
     /* The variable req_caseopt contains either the REQ_CASELESS value or zero,
-     according to the current setting of the caseless flag. REQ_CASELESS is a bit
+     according to the current setting of the ignores-case flag. REQ_CASELESS is a bit
      value > 255. It is added into the firstbyte or reqbyte variables to record the
      case status of the value. This is used only for ASCII characters. */
     
-    int req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS : 0;
+    int req_caseopt = (options & PCRE_CASELESS) ? REQ_CASELESS : 0;
     
     /* Switch on next character until the end of the branch */
     
@@ -1953,7 +1953,7 @@ compile_branch(int options, int* brackets, uschar** codeptr,
                     mclength = 1;
                     mcbuffer[0] = c;
                     
-                    if (options & PCRE_CASELESS && (c | 0x20) >= 'a' && (c | 0x20) <= 'z') {
+                    if ((options & PCRE_CASELESS) && (c | 0x20) >= 'a' && (c | 0x20) <= 'z') {
                         *code++ = OP_ASCII_LETTER_NC;
                         *code++ = c | 0x20;
                     } else {
@@ -2255,52 +2255,45 @@ Arguments:
 Returns:         true or false
 */
 
-static bool
-is_startline(const uschar *code, unsigned int bracket_map,
-  unsigned int backref_map)
+static bool canApplyFirstCharOptimization(const uschar* code, unsigned int bracket_map, unsigned int backref_map)
 {
-do {
-   const uschar *scode = first_significant_code(code + 1+LINK_SIZE, false);
-   int op = *scode;
-
-   /* Capturing brackets */
-
-   if (op > OP_BRA)
-     {
-     int new_map;
-     op -= OP_BRA;
-     if (op > EXTRACT_BASIC_MAX) op = GET2(scode, 2+LINK_SIZE);
-     new_map = bracket_map | ((op < 32)? (1 << op) : 1);
-     if (!is_startline(scode, new_map, backref_map)) return false;
-     }
-
-   /* Other brackets */
-
-   else if (op == OP_BRA || op == OP_ASSERT || op == OP_ONCE)
-     { if (!is_startline(scode, bracket_map, backref_map)) return false; }
-
-   /* .* means "start at start or after \n" if it isn't in brackets that
-   may be referenced. */
-
-   else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR)
-     {
-     if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return false;
-     }
-
-   /* Check for explicit circumflex */
-
-   else if (op != OP_CIRC) return false;
-
-   /* Move on to the next alternative */
-
-   code += GET(code, 1);
-   }
-while (*code == OP_ALT);  /* Loop for each alternative */
-return true;
+    do {
+        const uschar* scode = first_significant_code(code + 1 + LINK_SIZE, false);
+        int op = *scode;
+        
+        /* Capturing brackets */
+        if (op > OP_BRA) {
+            op -= OP_BRA;
+            if (op > EXTRACT_BASIC_MAX)
+                op = GET2(scode, 2+LINK_SIZE);
+            int new_map = bracket_map | ((op < 32)? (1 << op) : 1);
+            if (!canApplyFirstCharOptimization(scode, new_map, backref_map))
+                return false;
+        }
+        
+        /* Other brackets */
+        else if (op == OP_BRA || op == OP_ASSERT || op == OP_ONCE) {
+            if (!canApplyFirstCharOptimization(scode, bracket_map, backref_map))
+                return false;
+        
+        /* .* means "start at start or after \n" if it isn't in brackets that
+         may be referenced. */
+        
+        } else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR) {
+            if (scode[1] != OP_ANY || (bracket_map & backref_map))
+                return false;
+        } else if (op != OP_CIRC) /* Check for explicit circumflex */
+            return false;
+        
+        /* Move on to the next alternative */
+        
+        code += GET(code, 1);
+    }
+    while (*code == OP_ALT);  /* Loop for each alternative */
+    return true;
 }
 
 
-
 /*************************************************
 *       Check for asserted fixed first char      *
 *************************************************/
@@ -2332,40 +2325,40 @@ static int find_firstassertedchar(const uschar* code, int options, bool inassert
             op = OP_BRA;
         
         switch(op) {
-            default:
+        default:
+            return -1;
+            
+        case OP_BRA:
+        case OP_ASSERT:
+        case OP_ONCE: {
+            int d;
+            if ((d = find_firstassertedchar(scode, options, op == OP_ASSERT)) < 0)
                 return -1;
-                
-            case OP_BRA:
-            case OP_ASSERT:
-            case OP_ONCE: {
-                int d;
-                if ((d = find_firstassertedchar(scode, options, op == OP_ASSERT)) < 0)
-                    return -1;
-                if (c < 0)
-                    c = d;
-                else if (c != d)
-                    return -1;
-                break;
+            if (c < 0)
+                c = d;
+            else if (c != d)
+                return -1;
+            break;
+        }
+        case OP_EXACT:       /* Fall through */
+            scode += 2;
+            
+        case OP_CHAR:
+        case OP_CHARNC:
+        case OP_ASCII_CHAR:
+        case OP_ASCII_LETTER_NC:
+        case OP_PLUS:
+        case OP_MINPLUS:
+            if (!inassert)
+                return -1;
+            if (c < 0) {
+                c = scode[1];
+                if (options & PCRE_CASELESS)
+                    c |= REQ_CASELESS;
             }
-            case OP_EXACT:       /* Fall through */
-                scode += 2;
-                
-            case OP_CHAR:
-            case OP_CHARNC:
-            case OP_ASCII_CHAR:
-            case OP_ASCII_LETTER_NC:
-            case OP_PLUS:
-            case OP_MINPLUS:
-                if (!inassert)
-                    return -1;
-                if (c < 0) {
-                    c = scode[1];
-                    if (options & PCRE_CASELESS)
-                        c |= REQ_CASELESS;
-                }
-                else if (c != scode[1])
-                    return -1;
-                break;
+            else if (c != scode[1])
+                return -1;
+            break;
         }
         
         code += GET(code, 1);
@@ -2883,13 +2876,13 @@ static void printCompiledRegExp(JSRegExp* re, int length)
     if (re->options) {
         printf("%s%s%s\n",
                ((re->options & PCRE_ANCHORED) != 0)? "anchored " : "",
-               ((re->options & PCRE_CASELESS) != 0)? "caseless " : "",
+               ((re->options & PCRE_CASELESS) != 0)? "ignores case " : "",
                ((re->options & PCRE_MULTILINE) != 0)? "multiline " : "");
     }
     
     if (re->options & PCRE_FIRSTSET) {
         char ch = re->first_byte & 255;
-        const char* caseless = ((re->first_byte & REQ_CASELESS) == 0) ? "" : " (caseless)";
+        const char* caseless = (re->first_byte & REQ_CASELESS) ? " (ignores case)" : "";
         if (isASCIIAlphanumeric(ch))
             printf("First char = %c%s\n", ch, caseless);
         else
@@ -3029,7 +3022,7 @@ JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
      
      Otherwise, if we know what the first character has to be, save it, because that
      speeds up unanchored matches no end. If not, see if we can set the
-     PCRE_STARTLINE flag. This is helpful for multiline matches when all branches
+     OptionUseMultiLineFirstCharOptimization flag. This is helpful for multiline matches when all branches
      start with ^. and also when all branches start with .* for non-DOTALL matches.
      */
     
@@ -3047,8 +3040,8 @@ JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
                 re->options |= PCRE_FIRSTSET;
             }
         }
-        else if (is_startline(codestart, 0, compile_block.backref_map))
-            re->options |= PCRE_STARTLINE;
+        else if (canApplyFirstCharOptimization(codestart, 0, compile_block.backref_map))
+            re->options |= OptionUseMultiLineFirstCharOptimization;
     }
     
     /* For an anchored pattern, we use the "required byte" only if it follows a