00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #ifdef __cplusplus
00039 extern "C" {
00040 #endif
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 #ifdef DEBUG
00054 #define DPRINTF(p) printf p
00055 #else
00056 #define DPRINTF(p) 
00057 #endif
00058 
00059 
00060 
00061 
00062 #include "pcreinternal.h"
00063 
00064 
00065 
00066 
00067 #ifdef __cplusplus
00068 #define class pcre_class
00069 #endif
00070 
00071 
00072 
00073 
00074 
00075 #define BRASTACK_SIZE 200
00076 
00077 
00078 
00079 
00080 static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
00081 static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
00082 
00083 
00084 
00085 #ifdef DEBUG
00086 static const char *OP_names[] = {
00087   "End", "\\A", "\\B", "\\b", "\\D", "\\d",
00088   "\\S", "\\s", "\\W", "\\w", "\\Z", "\\z",
00089   "Opt", "^", "$", "Any", "chars", "not",
00090   "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
00091   "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
00092   "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
00093   "*", "*?", "+", "+?", "?", "??", "{", "{",
00094   "class", "Ref",
00095   "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not",
00096   "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cref",
00097   "Brazero", "Braminzero", "Bra"
00098 };
00099 #endif
00100 
00101 
00102 
00103 
00104 
00105 
00106 static const short int escapes[] = {
00107     0,      0,      0,      0,      0,      0,      0,      0,   
00108     0,      0,    ':',    ';',    '<',    '=',    '>',    '?',   
00109   '@', -ESC_A, -ESC_B,      0, -ESC_D,      0,      0,      0,   
00110     0,      0,      0,      0,      0,      0,      0,      0,   
00111     0,      0,      0, -ESC_S,      0,      0,      0, -ESC_W,   
00112     0,      0, -ESC_Z,    '[',   '\\',    ']',    '^',    '_',   
00113   '`',      7, -ESC_b,      0, -ESC_d,     27,   '\f',      0,   
00114     0,      0,      0,      0,      0,      0,   '\n',      0,   
00115     0,      0,   '\r', -ESC_s,   '\t',      0,      0, -ESC_w,   
00116     0,      0, -ESC_z                                            
00117 };
00118 
00119 
00120 
00121 static BOOL
00122   compile_regex(int, int, int *, uschar **, const uschar **, const char **,
00123     BOOL, int, compile_data *);
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 void *(*vmdpcre_malloc)(size_t) = malloc;
00137 void  (*vmdpcre_free)(void *) = free;
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 #include "pcretables.h"
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 const char *
00161 vmdpcre_version(void)
00162 {
00163 return PCRE_VERSION;
00164 }
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 
00187 int
00188 vmdpcre_info(const pcre *external_re, int *optptr, int *first_char)
00189 {
00190 const real_pcre *re = (const real_pcre *)external_re;
00191 if (re == NULL) return PCRE_ERROR_NULL;
00192 if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
00193 if (optptr != NULL) *optptr = (re->options & PUBLIC_OPTIONS);
00194 if (first_char != NULL)
00195   *first_char = ((re->options & PCRE_FIRSTSET) != 0)? re->first_char :
00196      ((re->options & PCRE_STARTLINE) != 0)? -1 : -2;
00197 return re->top_bracket;
00198 }
00199 
00200 
00201 
00202 
00203 #ifdef DEBUG
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 static void
00221 pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
00222 {
00223 int c;
00224 if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
00225 while (length-- > 0)
00226   if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c);
00227 }
00228 #endif
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 static int
00257 check_escape(const uschar **ptrptr, const char **errorptr, int bracount,
00258   int options, BOOL isclass, compile_data *cd)
00259 {
00260 const uschar *ptr = *ptrptr;
00261 int c = *(ptr+1) & 255;   
00262 int i;
00263 ++ptr;
00264 
00265 if (c == 0) *errorptr = ERR1;
00266 
00267 
00268 
00269 else if (c < '0' || c > 'z') {}
00270 
00271 
00272 
00273 
00274 else if ((i = escapes[c - '0']) != 0) c = i;
00275 
00276 
00277 
00278 else
00279   {
00280   const uschar *oldptr;
00281   switch (c)
00282     {
00283     
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295     case '1': case '2': case '3': case '4': case '5':
00296     case '6': case '7': case '8': case '9':
00297 
00298     if (!isclass)
00299       {
00300       oldptr = ptr;
00301       c -= '0';
00302       while ((cd->ctypes[ptr[1]] & ctype_digit) != 0)
00303         c = c * 10 + *(++ptr) - '0';
00304       if (c < 10 || c <= bracount)
00305         {
00306         c = -(ESC_REF + c);
00307         break;
00308         }
00309       ptr = oldptr;      
00310       }
00311 
00312     
00313 
00314 
00315 
00316     if ((c = *ptr) >= '8')
00317       {
00318       ptr--;
00319       c = 0;
00320       break;
00321       }
00322 
00323     
00324 
00325 
00326     case '0':
00327     c -= '0';
00328     while(i++ < 2 && (cd->ctypes[ptr[1]] & ctype_digit) != 0 &&
00329       ptr[1] != '8' && ptr[1] != '9')
00330         c = c * 8 + *(++ptr) - '0';
00331     break;
00332 
00333     
00334 
00335     case 'x':
00336     c = 0;
00337     while (i++ < 2 && (cd->ctypes[ptr[1]] & ctype_xdigit) != 0)
00338       {
00339       ptr++;
00340       c = c * 16 + cd->lcc[*ptr] -
00341         (((cd->ctypes[*ptr] & ctype_digit) != 0)? '0' : 'W');
00342       }
00343     break;
00344 
00345     case 'c':
00346     c = *(++ptr);
00347     if (c == 0)
00348       {
00349       *errorptr = ERR2;
00350       return 0;
00351       }
00352 
00353     
00354 
00355     if (c >= 'a' && c <= 'z') c = cd->fcc[c];
00356     c ^= 0x40;
00357     break;
00358 
00359     
00360 
00361 
00362 
00363 
00364 
00365     default:
00366     if ((options & PCRE_EXTRA) != 0) switch(c)
00367       {
00368       default:
00369       *errorptr = ERR3;
00370       break;
00371       }
00372     break;
00373     }
00374   }
00375 
00376 *ptrptr = ptr;
00377 return c;
00378 }
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 static BOOL
00399 is_counted_repeat(const uschar *p, compile_data *cd)
00400 {
00401 if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
00402 while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
00403 if (*p == '}') return TRUE;
00404 
00405 if (*p++ != ',') return FALSE;
00406 if (*p == '}') return TRUE;
00407 
00408 if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
00409 while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
00410 return (*p == '}');
00411 }
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 static const uschar *
00436 read_repeat_counts(const uschar *p, int *minp, int *maxp,
00437   const char **errorptr, compile_data *cd)
00438 {
00439 int min = 0;
00440 int max = -1;
00441 
00442 while ((cd->ctypes[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0';
00443 
00444 if (*p == '}') max = min; else
00445   {
00446   if (*(++p) != '}')
00447     {
00448     max = 0;
00449     while((cd->ctypes[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0';
00450     if (max < min)
00451       {
00452       *errorptr = ERR4;
00453       return p;
00454       }
00455     }
00456   }
00457 
00458 
00459 
00460 
00461 if (min > 65535 || max > 65535)
00462   *errorptr = ERR5;
00463 else
00464   {
00465   *minp = min;
00466   *maxp = max;
00467   }
00468 return p;
00469 }
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 static int
00487 find_fixedlength(uschar *code)
00488 {
00489 int length = -1;
00490 
00491 register int branchlength = 0;
00492 register uschar *cc = code + 3;
00493 
00494 
00495 
00496 
00497 for (;;)
00498   {
00499   int d;
00500   register int op = *cc;
00501   if (op >= OP_BRA) op = OP_BRA;
00502 
00503   switch (op)
00504     {
00505     case OP_BRA:
00506     case OP_ONCE:
00507     case OP_COND:
00508     d = find_fixedlength(cc);
00509     if (d < 0) return -1;
00510     branchlength += d;
00511     do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT);
00512     cc += 3;
00513     break;
00514 
00515     
00516 
00517 
00518 
00519     case OP_ALT:
00520     case OP_KET:
00521     case OP_KETRMAX:
00522     case OP_KETRMIN:
00523     case OP_END:
00524     if (length < 0) length = branchlength;
00525       else if (length != branchlength) return -1;
00526     if (*cc != OP_ALT) return length;
00527     cc += 3;
00528     branchlength = 0;
00529     break;
00530 
00531     
00532 
00533     case OP_ASSERT:
00534     case OP_ASSERT_NOT:
00535     case OP_ASSERTBACK:
00536     case OP_ASSERTBACK_NOT:
00537     do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT);
00538     cc += 3;
00539     break;
00540 
00541     
00542 
00543     case OP_REVERSE:
00544     cc++;
00545 
00546     case OP_CREF:
00547     case OP_OPT:
00548     cc++;
00549     
00550 
00551     case OP_SOD:
00552     case OP_EOD:
00553     case OP_EODN:
00554     case OP_CIRC:
00555     case OP_DOLL:
00556     case OP_NOT_WORD_BOUNDARY:
00557     case OP_WORD_BOUNDARY:
00558     cc++;
00559     break;
00560 
00561     
00562 
00563     case OP_CHARS:
00564     branchlength += *(++cc);
00565     cc += *cc + 1;
00566     break;
00567 
00568     
00569 
00570     case OP_EXACT:
00571     case OP_TYPEEXACT:
00572     branchlength += (cc[1] << 8) + cc[2];
00573     cc += 4;
00574     break;
00575 
00576     
00577 
00578     case OP_NOT_DIGIT:
00579     case OP_DIGIT:
00580     case OP_NOT_WHITESPACE:
00581     case OP_WHITESPACE:
00582     case OP_NOT_WORDCHAR:
00583     case OP_WORDCHAR:
00584     case OP_ANY:
00585     branchlength++;
00586     cc++;
00587     break;
00588 
00589 
00590     
00591 
00592     case OP_CLASS:
00593     cc += (*cc == OP_REF)? 2 : 33;
00594 
00595     switch (*cc)
00596       {
00597       case OP_CRSTAR:
00598       case OP_CRMINSTAR:
00599       case OP_CRQUERY:
00600       case OP_CRMINQUERY:
00601       return -1;
00602 
00603       case OP_CRRANGE:
00604       case OP_CRMINRANGE:
00605       if ((cc[1] << 8) + cc[2] != (cc[3] << 8) + cc[4]) return -1;
00606       branchlength += (cc[1] << 8) + cc[2];
00607       cc += 5;
00608       break;
00609 
00610       default:
00611       branchlength++;
00612       }
00613     break;
00614 
00615     
00616 
00617     default:
00618     return -1;
00619     }
00620   }
00621 
00622 }
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632 
00633 
00634 
00635 
00636 
00637 
00638 
00639 
00640 
00641 
00642 
00643 
00644 
00645 
00646 static BOOL
00647 compile_branch(int options, int *brackets, uschar **codeptr,
00648   const uschar **ptrptr, const char **errorptr, int *optchanged,
00649   compile_data *cd)
00650 {
00651 int repeat_type, op_type;
00652 int repeat_min, repeat_max;
00653 int bravalue, length;
00654 int greedy_default, greedy_non_default;
00655 register int c;
00656 register uschar *code = *codeptr;
00657 uschar *tempcode;
00658 const uschar *ptr = *ptrptr;
00659 const uschar *tempptr;
00660 uschar *previous = NULL;
00661 uschar class[32];
00662 
00663 
00664 
00665 greedy_default = ((options & PCRE_UNGREEDY) != 0);
00666 greedy_non_default = greedy_default ^ 1;
00667 
00668 
00669 
00670 for (;; ptr++)
00671   {
00672   BOOL negate_class;
00673   int class_charcount;
00674   int class_lastchar;
00675   int newoptions;
00676   int condref;
00677 
00678   c = *ptr;
00679   if ((options & PCRE_EXTENDED) != 0)
00680     {
00681     if ((cd->ctypes[c] & ctype_space) != 0) continue;
00682     if (c == '#')
00683       {
00684       while ((c = *(++ptr)) != 0 && c != '\n');
00685       continue;
00686       }
00687     }
00688 
00689   switch(c)
00690     {
00691     
00692 
00693     case 0:
00694     case '|':
00695     case ')':
00696     *codeptr = code;
00697     *ptrptr = ptr;
00698     return TRUE;
00699 
00700     
00701 
00702     case '^':
00703     previous = NULL;
00704     *code++ = OP_CIRC;
00705     break;
00706 
00707     case '$':
00708     previous = NULL;
00709     *code++ = OP_DOLL;
00710     break;
00711 
00712     case '.':
00713     previous = code;
00714     *code++ = OP_ANY;
00715     break;
00716 
00717     
00718 
00719 
00720 
00721 
00722     case '[':
00723     previous = code;
00724     *code++ = OP_CLASS;
00725 
00726     
00727 
00728     if ((c = *(++ptr)) == '^')
00729       {
00730       negate_class = TRUE;
00731       c = *(++ptr);
00732       }
00733     else negate_class = FALSE;
00734 
00735     
00736 
00737 
00738     class_charcount = 0;
00739     class_lastchar = -1;
00740 
00741     
00742 
00743 
00744 
00745 
00746     memset(class, 0, 32 * sizeof(uschar));
00747 
00748     
00749 
00750 
00751     do
00752       {
00753       if (c == 0)
00754         {
00755         *errorptr = ERR6;
00756         goto FAILED;
00757         }
00758 
00759       
00760 
00761 
00762 
00763 
00764 
00765 
00766 
00767       if (c == '\\')
00768         {
00769         c = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
00770         if (-c == ESC_b) c = '\b';
00771         else if (c < 0)
00772           {
00773           register const uschar *cbits = cd->cbits;
00774           class_charcount = 10;
00775           switch (-c)
00776             {
00777             case ESC_d:
00778             for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_digit];
00779             continue;
00780 
00781             case ESC_D:
00782             for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_digit];
00783             continue;
00784 
00785             case ESC_w:
00786             for (c = 0; c < 32; c++)
00787               class[c] |= (cbits[c+cbit_digit] | cbits[c+cbit_word]);
00788             continue;
00789 
00790             case ESC_W:
00791             for (c = 0; c < 32; c++)
00792               class[c] |= ~(cbits[c+cbit_digit] | cbits[c+cbit_word]);
00793             continue;
00794 
00795             case ESC_s:
00796             for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_space];
00797             continue;
00798 
00799             case ESC_S:
00800             for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_space];
00801             continue;
00802 
00803             default:
00804             *errorptr = ERR7;
00805             goto FAILED;
00806             }
00807           }
00808         
00809         }
00810 
00811       
00812 
00813 
00814 
00815       if (ptr[1] == '-' && ptr[2] != ']')
00816         {
00817         int d;
00818         ptr += 2;
00819         d = *ptr;
00820 
00821         if (d == 0)
00822           {
00823           *errorptr = ERR6;
00824           goto FAILED;
00825           }
00826 
00827         
00828 
00829 
00830         if (d == '\\')
00831           {
00832           d = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
00833           if (d < 0)
00834             {
00835             if (d == -ESC_b) d = '\b'; else
00836               {
00837               *errorptr = ERR7;
00838               goto FAILED;
00839               }
00840             }
00841           }
00842 
00843         if (d < c)
00844           {
00845           *errorptr = ERR8;
00846           goto FAILED;
00847           }
00848 
00849         for (; c <= d; c++)
00850           {
00851           class[c/8] |= (1 << (c&7));
00852           if ((options & PCRE_CASELESS) != 0)
00853             {
00854             int uc = cd->fcc[c];           
00855             class[uc/8] |= (1 << (uc&7));
00856             }
00857           class_charcount++;                
00858           class_lastchar = c;
00859           }
00860         continue;   
00861         }
00862 
00863       
00864 
00865 
00866       class [c/8] |= (1 << (c&7));
00867       if ((options & PCRE_CASELESS) != 0)
00868         {
00869         c = cd->fcc[c];   
00870         class[c/8] |= (1 << (c&7));
00871         }
00872       class_charcount++;
00873       class_lastchar = c;
00874       }
00875 
00876     
00877 
00878 
00879     while ((c = *(++ptr)) != ']');
00880 
00881     
00882 
00883 
00884 
00885 
00886     if (class_charcount == 1 && class_lastchar >= 0)
00887       {
00888       if (negate_class)
00889         {
00890         code[-1] = OP_NOT;
00891         }
00892       else
00893         {
00894         code[-1] = OP_CHARS;
00895         *code++ = 1;
00896         }
00897       *code++ = class_lastchar;
00898       }
00899 
00900     
00901 
00902 
00903     else
00904       {
00905       if (negate_class)
00906         for (c = 0; c < 32; c++) code[c] = ~class[c];
00907       else
00908         memcpy(code, class, 32);
00909       code += 32;
00910       }
00911     break;
00912 
00913     
00914 
00915     case '{':
00916     if (!is_counted_repeat(ptr+1, cd)) goto NORMAL_CHAR;
00917     ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorptr, cd);
00918     if (*errorptr != NULL) goto FAILED;
00919     goto REPEAT;
00920 
00921     case '*':
00922     repeat_min = 0;
00923     repeat_max = -1;
00924     goto REPEAT;
00925 
00926     case '+':
00927     repeat_min = 1;
00928     repeat_max = -1;
00929     goto REPEAT;
00930 
00931     case '?':
00932     repeat_min = 0;
00933     repeat_max = 1;
00934 
00935     REPEAT:
00936     if (previous == NULL)
00937       {
00938       *errorptr = ERR9;
00939       goto FAILED;
00940       }
00941 
00942     
00943 
00944 
00945 
00946     if (ptr[1] == '?')
00947       { repeat_type = greedy_non_default; ptr++; }
00948     else repeat_type = greedy_default;
00949 
00950     
00951 
00952 
00953     if (repeat_max == 0) code = previous;
00954 
00955     
00956 
00957 
00958 
00959     else if (*previous == OP_CHARS)
00960       {
00961       int len = previous[1];
00962       if (len == 1)
00963         {
00964         c = previous[2];
00965         code = previous;
00966         }
00967       else
00968         {
00969         c = previous[len+1];
00970         previous[1]--;
00971         code--;
00972         }
00973       op_type = 0;                 
00974       goto OUTPUT_SINGLE_REPEAT;   
00975       }
00976 
00977     
00978 
00979 
00980 
00981     else if ((int)*previous == OP_NOT)
00982       {
00983       op_type = OP_NOTSTAR - OP_STAR;  
00984       c = previous[1];
00985       code = previous;
00986       goto OUTPUT_SINGLE_REPEAT;
00987       }
00988 
00989     
00990 
00991 
00992 
00993     else if ((int)*previous < OP_EODN || *previous == OP_ANY)
00994       {
00995       op_type = OP_TYPESTAR - OP_STAR;  
00996       c = *previous;
00997       code = previous;
00998 
00999       OUTPUT_SINGLE_REPEAT:
01000       repeat_type += op_type;      
01001 
01002       
01003 
01004 
01005       if (repeat_min == 0)
01006         {
01007         if (repeat_max == -1) *code++ = OP_STAR + repeat_type;
01008           else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;
01009         else
01010           {
01011           *code++ = OP_UPTO + repeat_type;
01012           *code++ = repeat_max >> 8;
01013           *code++ = (repeat_max & 255);
01014           }
01015         }
01016 
01017       
01018 
01019       else if (repeat_min == 1 && repeat_max == -1)
01020         *code++ = OP_PLUS + repeat_type;
01021 
01022       
01023 
01024 
01025       else
01026         {
01027         if (repeat_min != 1)
01028           {
01029           *code++ = OP_EXACT + op_type;  
01030           *code++ = repeat_min >> 8;
01031           *code++ = (repeat_min & 255);
01032           }
01033 
01034         
01035 
01036 
01037 
01038 
01039 
01040 
01041         else if (*previous == OP_CHARS)
01042           {
01043           if (code == previous) code += 2; else previous[1]++;
01044           }
01045 
01046         
01047 
01048 
01049         else if (*previous == OP_NOT) code++;
01050 
01051         
01052 
01053         if (repeat_max < 0)
01054           {
01055           *code++ = c;
01056           *code++ = OP_STAR + repeat_type;
01057           }
01058 
01059         
01060 
01061         else if (repeat_max != repeat_min)
01062           {
01063           *code++ = c;
01064           repeat_max -= repeat_min;
01065           *code++ = OP_UPTO + repeat_type;
01066           *code++ = repeat_max >> 8;
01067           *code++ = (repeat_max & 255);
01068           }
01069         }
01070 
01071       
01072 
01073       *code++ = c;
01074       }
01075 
01076     
01077 
01078 
01079     else if (*previous == OP_CLASS || *previous == OP_REF)
01080       {
01081       if (repeat_min == 0 && repeat_max == -1)
01082         *code++ = OP_CRSTAR + repeat_type;
01083       else if (repeat_min == 1 && repeat_max == -1)
01084         *code++ = OP_CRPLUS + repeat_type;
01085       else if (repeat_min == 0 && repeat_max == 1)
01086         *code++ = OP_CRQUERY + repeat_type;
01087       else
01088         {
01089         *code++ = OP_CRRANGE + repeat_type;
01090         *code++ = repeat_min >> 8;
01091         *code++ = repeat_min & 255;
01092         if (repeat_max == -1) repeat_max = 0;  
01093         *code++ = repeat_max >> 8;
01094         *code++ = repeat_max & 255;
01095         }
01096       }
01097 
01098     
01099 
01100 
01101     else if ((int)*previous >= OP_BRA || (int)*previous == OP_ONCE ||
01102              (int)*previous == OP_COND)
01103       {
01104       register int i;
01105       int ketoffset = 0;
01106       int len = code - previous;
01107       uschar *bralink = NULL;
01108 
01109       
01110 
01111 
01112 
01113 
01114 
01115       if (repeat_max == -1)
01116         {
01117         register uschar *ket = previous;
01118         do ket += (ket[1] << 8) + ket[2]; while (*ket != OP_KET);
01119         ketoffset = code - ket;
01120         }
01121 
01122       
01123 
01124 
01125 
01126 
01127 
01128 
01129       if (repeat_min == 0)
01130         {
01131         
01132 
01133 
01134         if (repeat_max == 0)
01135           {
01136           code = previous;
01137           previous = NULL;
01138           break;
01139           }
01140 
01141         
01142 
01143 
01144         if (repeat_max <= 1)
01145           {
01146           memmove(previous+1, previous, len);
01147           code++;
01148           *previous++ = OP_BRAZERO + repeat_type;
01149           }
01150 
01151         
01152 
01153 
01154 
01155 
01156 
01157 
01158         else
01159           {
01160           int offset;
01161           memmove(previous+4, previous, len);
01162           code += 4;
01163           *previous++ = OP_BRAZERO + repeat_type;
01164           *previous++ = OP_BRA;
01165 
01166           
01167 
01168 
01169           offset = (bralink == NULL)? 0 : previous - bralink;
01170           bralink = previous;
01171           *previous++ = offset >> 8;
01172           *previous++ = offset & 255;
01173           }
01174 
01175         repeat_max--;
01176         }
01177 
01178       
01179 
01180 
01181 
01182       else
01183         {
01184         for (i = 1; i < repeat_min; i++)
01185           {
01186           memcpy(code, previous, len);
01187           code += len;
01188           }
01189         if (repeat_max > 0) repeat_max -= repeat_min;
01190         }
01191 
01192       
01193 
01194 
01195 
01196 
01197 
01198       if (repeat_max >= 0)
01199         {
01200         for (i = repeat_max - 1; i >= 0; i--)
01201           {
01202           *code++ = OP_BRAZERO + repeat_type;
01203 
01204           
01205 
01206 
01207           if (i != 0)
01208             {
01209             int offset;
01210             *code++ = OP_BRA;
01211             offset = (bralink == NULL)? 0 : code - bralink;
01212             bralink = code;
01213             *code++ = offset >> 8;
01214             *code++ = offset & 255;
01215             }
01216 
01217           memcpy(code, previous, len);
01218           code += len;
01219           }
01220 
01221         
01222 
01223 
01224         while (bralink != NULL)
01225           {
01226           int oldlinkoffset;
01227           int offset = code - bralink + 1;
01228           uschar *bra = code - offset;
01229           oldlinkoffset = (bra[1] << 8) + bra[2];
01230           bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;
01231           *code++ = OP_KET;
01232           *code++ = bra[1] = offset >> 8;
01233           *code++ = bra[2] = (offset & 255);
01234           }
01235         }
01236 
01237       
01238 
01239 
01240 
01241 
01242       else code[-ketoffset] = OP_KETRMAX + repeat_type;
01243 
01244 
01245 #ifdef NEVER
01246       
01247 
01248 
01249 
01250 
01251       if (repeat_min > 0 && (repeat_max == -1 || repeat_max == repeat_min))
01252         {
01253         for (i = 1; i < repeat_min; i++)
01254           {
01255           memcpy(code, previous, len);
01256           code += len;
01257           }
01258         }
01259 
01260       
01261 
01262 
01263 
01264       else
01265         {
01266         if (repeat_min == 0)
01267           {
01268           memmove(previous+1, previous, len);
01269           code++;
01270           *previous++ = OP_BRAZERO + repeat_type;
01271           }
01272 
01273         for (i = 1; i < repeat_min; i++)
01274           {
01275           memcpy(code, previous, len);
01276           code += len;
01277           }
01278 
01279         for (i = (repeat_min > 0)? repeat_min : 1; i < repeat_max; i++)
01280           {
01281           *code++ = OP_BRAZERO + repeat_type;
01282           memcpy(code, previous, len);
01283           code += len;
01284           }
01285         }
01286 
01287       
01288 
01289 
01290 
01291 
01292       if (repeat_max == -1) code[-ketoffset] = OP_KETRMAX + repeat_type;
01293 #endif
01294 
01295 
01296       }
01297 
01298     
01299 
01300     else
01301       {
01302       *errorptr = ERR11;
01303       goto FAILED;
01304       }
01305 
01306     
01307 
01308     previous = NULL;
01309     break;
01310 
01311 
01312     
01313 
01314 
01315 
01316 
01317 
01318 
01319     case '(':
01320     newoptions = options;
01321     condref = -1;
01322 
01323     if (*(++ptr) == '?')
01324       {
01325       int set, unset;
01326       int *optset;
01327 
01328       switch (*(++ptr))
01329         {
01330         case '#':                 
01331         ptr++;
01332         while (*ptr != ')') ptr++;
01333         continue;
01334 
01335         case ':':                 
01336         bravalue = OP_BRA;
01337         ptr++;
01338         break;
01339 
01340         case '(':
01341         bravalue = OP_COND;       
01342         if ((cd->ctypes[*(++ptr)] & ctype_digit) != 0)
01343           {
01344           condref = *ptr - '0';
01345           while (*(++ptr) != ')') condref = condref*10 + *ptr - '0';
01346           ptr++;
01347           }
01348         else ptr--;
01349         break;
01350 
01351         case '=':                 
01352         bravalue = OP_ASSERT;
01353         ptr++;
01354         break;
01355 
01356         case '!':                 
01357         bravalue = OP_ASSERT_NOT;
01358         ptr++;
01359         break;
01360 
01361         case '<':                 
01362         switch (*(++ptr))
01363           {
01364           case '=':               
01365           bravalue = OP_ASSERTBACK;
01366           ptr++;
01367           break;
01368 
01369           case '!':               
01370           bravalue = OP_ASSERTBACK_NOT;
01371           ptr++;
01372           break;
01373 
01374           default:                
01375           *errorptr = ERR24;
01376           goto FAILED;
01377           }
01378         break;
01379 
01380         case '>':                 
01381         bravalue = OP_ONCE;
01382         ptr++;
01383         break;
01384 
01385         default:                  
01386         set = unset = 0;
01387         optset = &set;
01388 
01389         while (*ptr != ')' && *ptr != ':')
01390           {
01391           switch (*ptr++)
01392             {
01393             case '-': optset = &unset; break;
01394 
01395             case 'i': *optset |= PCRE_CASELESS; break;
01396             case 'm': *optset |= PCRE_MULTILINE; break;
01397             case 's': *optset |= PCRE_DOTALL; break;
01398             case 'x': *optset |= PCRE_EXTENDED; break;
01399             case 'U': *optset |= PCRE_UNGREEDY; break;
01400             case 'X': *optset |= PCRE_EXTRA; break;
01401 
01402             default:
01403             *errorptr = ERR12;
01404             goto FAILED;
01405             }
01406           }
01407 
01408         
01409 
01410         newoptions = (options | set) & (~unset);
01411 
01412         
01413 
01414 
01415 
01416 
01417 
01418 
01419 
01420 
01421         if (*ptr == ')')
01422           {
01423           if ((options & PCRE_INGROUP) != 0 &&
01424               (options & PCRE_IMS) != (newoptions & PCRE_IMS))
01425             {
01426             *code++ = OP_OPT;
01427             *code++ = *optchanged = newoptions & PCRE_IMS;
01428             }
01429           options = newoptions;  
01430           previous = NULL;       
01431           continue;              
01432           }
01433 
01434         
01435 
01436 
01437 
01438 
01439         bravalue = OP_BRA;
01440         ptr++;
01441         }
01442       }
01443 
01444     
01445 
01446     else
01447       {
01448       if (++(*brackets) > EXTRACT_MAX)
01449         {
01450         *errorptr = ERR13;
01451         goto FAILED;
01452         }
01453       bravalue = OP_BRA + *brackets;
01454       }
01455 
01456     
01457 
01458 
01459 
01460 
01461     previous = (bravalue >= OP_ONCE)? code : NULL;
01462     *code = bravalue;
01463     tempcode = code;
01464 
01465     if (!compile_regex(
01466          options | PCRE_INGROUP,       
01467          ((options & PCRE_IMS) != (newoptions & PCRE_IMS))?
01468            newoptions & PCRE_IMS : -1, 
01469          brackets,                     
01470          &tempcode,                    
01471          &ptr,                         
01472          errorptr,                     
01473          (bravalue == OP_ASSERTBACK ||
01474           bravalue == OP_ASSERTBACK_NOT), 
01475          condref,                      
01476          cd))                          
01477       goto FAILED;
01478 
01479     
01480 
01481 
01482 
01483 
01484     
01485 
01486 
01487     if (bravalue == OP_COND)
01488       {
01489       int branchcount = 0;
01490       uschar *tc = code;
01491 
01492       do {
01493          branchcount++;
01494          tc += (tc[1] << 8) | tc[2];
01495          }
01496       while (*tc != OP_KET);
01497 
01498       if (branchcount > 2)
01499         {
01500         *errorptr = ERR27;
01501         goto FAILED;
01502         }
01503       }
01504 
01505     
01506 
01507     code = tempcode;
01508 
01509     
01510 
01511     if (*ptr != ')')
01512       {
01513       *errorptr = ERR14;
01514       goto FAILED;
01515       }
01516     break;
01517 
01518     
01519 
01520 
01521 
01522     case '\\':
01523     tempptr = ptr;
01524     c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
01525 
01526     
01527 
01528 
01529 
01530 
01531 
01532 
01533     if (c < 0)
01534       {
01535       if (-c >= ESC_REF)
01536         {
01537         previous = code;
01538         *code++ = OP_REF;
01539         *code++ = -c - ESC_REF;
01540         }
01541       else
01542         {
01543         previous = (-c > ESC_b && -c < ESC_Z)? code : NULL;
01544         *code++ = -c;
01545         }
01546       continue;
01547       }
01548 
01549     
01550 
01551     ptr = tempptr;
01552     c = '\\';
01553 
01554     
01555 
01556 
01557 
01558     NORMAL_CHAR:
01559     default:
01560     previous = code;
01561     *code = OP_CHARS;
01562     code += 2;
01563     length = 0;
01564 
01565     do
01566       {
01567       if ((options & PCRE_EXTENDED) != 0)
01568         {
01569         if ((cd->ctypes[c] & ctype_space) != 0) continue;
01570         if (c == '#')
01571           {
01572           while ((c = *(++ptr)) != 0 && c != '\n');
01573           if (c == 0) break;
01574           continue;
01575           }
01576         }
01577 
01578       
01579 
01580 
01581 
01582       if (c == '\\')
01583         {
01584         tempptr = ptr;
01585         c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
01586         if (c < 0) { ptr = tempptr; break; }
01587         }
01588 
01589       
01590 
01591       *code++ = c;
01592       length++;
01593       }
01594 
01595     
01596 
01597     while (length < 255 && (cd->ctypes[c = *(++ptr)] & ctype_meta) == 0);
01598 
01599     
01600 
01601 
01602     previous[1] = length;
01603     if (length < 255) ptr--;
01604     break;
01605     }
01606   }                   
01607 
01608 
01609 
01610 
01611 
01612 FAILED:
01613 *ptrptr = ptr;
01614 return FALSE;
01615 }
01616 
01617 
01618 
01619 
01620 
01621 
01622 
01623 
01624 
01625 
01626 
01627 
01628 
01629 
01630 
01631 
01632 
01633 
01634 
01635 
01636 
01637 
01638 
01639 
01640 
01641 
01642 
01643 
01644 
01645 
01646 
01647 static BOOL
01648 compile_regex(int options, int optchanged, int *brackets, uschar **codeptr,
01649   const uschar **ptrptr, const char **errorptr, BOOL lookbehind, int condref,
01650   compile_data *cd)
01651 {
01652 const uschar *ptr = *ptrptr;
01653 uschar *code = *codeptr;
01654 uschar *last_branch = code;
01655 uschar *start_bracket = code;
01656 uschar *reverse_count = NULL;
01657 int oldoptions = options & PCRE_IMS;
01658 
01659 code += 3;
01660 
01661 
01662 
01663 
01664 if (condref > 0)
01665   {
01666   *code++ = OP_CREF;
01667   *code++ = condref;
01668   }
01669 
01670 
01671 
01672 for (;;)
01673   {
01674   int length;
01675 
01676   
01677 
01678   if (optchanged >= 0)
01679     {
01680     *code++ = OP_OPT;
01681     *code++ = optchanged;
01682     options = (options & ~PCRE_IMS) | optchanged;
01683     }
01684 
01685   
01686 
01687   if (lookbehind)
01688     {
01689     *code++ = OP_REVERSE;
01690     reverse_count = code;
01691     *code++ = 0;
01692     *code++ = 0;
01693     }
01694 
01695   
01696 
01697   if (!compile_branch(options,brackets,&code,&ptr,errorptr,&optchanged,cd))
01698     {
01699     *ptrptr = ptr;
01700     return FALSE;
01701     }
01702 
01703   
01704 
01705   length = code - last_branch;
01706   last_branch[1] = length >> 8;
01707   last_branch[2] = length & 255;
01708 
01709   
01710 
01711 
01712 
01713   if (lookbehind)
01714     {
01715     *code = OP_END;
01716     length = find_fixedlength(last_branch);
01717     DPRINTF(("fixed length = %d\n", length));
01718     if (length < 0)
01719       {
01720       *errorptr = ERR25;
01721       *ptrptr = ptr;
01722       return FALSE;
01723       }
01724     reverse_count[0] = (length >> 8);
01725     reverse_count[1] = length & 255;
01726     }
01727 
01728   
01729 
01730 
01731 
01732 
01733   if (*ptr != '|')
01734     {
01735     length = code - start_bracket;
01736     *code++ = OP_KET;
01737     *code++ = length >> 8;
01738     *code++ = length & 255;
01739     if (optchanged >= 0)
01740       {
01741       *code++ = OP_OPT;
01742       *code++ = oldoptions;
01743       }
01744     *codeptr = code;
01745     *ptrptr = ptr;
01746     return TRUE;
01747     }
01748 
01749   
01750 
01751   *code = OP_ALT;
01752   last_branch = code;
01753   code += 3;
01754   ptr++;
01755   }
01756 
01757 }
01758 
01759 
01760 
01761 
01762 
01763 
01764 
01765 
01766 
01767 
01768 
01769 
01770 
01771 
01772 
01773 
01774 
01775 
01776 
01777 
01778 
01779 
01780 
01781 
01782 static const uschar*
01783 first_significant_code(const uschar *code, int *options, int optbit,
01784   BOOL optstop)
01785 {
01786 for (;;)
01787   {
01788   switch ((int)*code)
01789     {
01790     case OP_OPT:
01791     if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit))
01792       {
01793       if (optstop) return code;
01794       *options = (int)code[1];
01795       }
01796     code += 2;
01797     break;
01798 
01799     case OP_CREF:
01800     code += 2;
01801     break;
01802 
01803     case OP_WORD_BOUNDARY:
01804     case OP_NOT_WORD_BOUNDARY:
01805     code++;
01806     break;
01807 
01808     case OP_ASSERT_NOT:
01809     case OP_ASSERTBACK:
01810     case OP_ASSERTBACK_NOT:
01811     do code += (code[1] << 8) + code[2]; while (*code == OP_ALT);
01812     code += 3;
01813     break;
01814 
01815     default:
01816     return code;
01817     }
01818   }
01819 
01820 }
01821 
01822 
01823 
01824 
01825 
01826 
01827 
01828 
01829 
01830 
01831 
01832 
01833 
01834 
01835 
01836 
01837 
01838 
01839 
01840 
01841 
01842 
01843 
01844 
01845 
01846 static BOOL
01847 is_anchored(register const uschar *code, int *options)
01848 {
01849 do {
01850    const uschar *scode = first_significant_code(code + 3, options,
01851      PCRE_MULTILINE, FALSE);
01852    register int op = *scode;
01853    if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
01854      { if (!is_anchored(scode, options)) return FALSE; }
01855    else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) &&
01856             (*options & PCRE_DOTALL) != 0)
01857      { if (scode[1] != OP_ANY) return FALSE; }
01858    else if (op != OP_SOD &&
01859            ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC))
01860      return FALSE;
01861    code += (code[1] << 8) + code[2];
01862    }
01863 while (*code == OP_ALT);
01864 return TRUE;
01865 }
01866 
01867 
01868 
01869 
01870 
01871 
01872 
01873 
01874 
01875 
01876 
01877 
01878 
01879 
01880 
01881 
01882 static BOOL
01883 is_startline(const uschar *code)
01884 {
01885 do {
01886    const uschar *scode = first_significant_code(code + 3, NULL, 0, FALSE);
01887    register int op = *scode;
01888    if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
01889      { if (!is_startline(scode)) return FALSE; }
01890    else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR)
01891      { if (scode[1] != OP_ANY) return FALSE; }
01892    else if (op != OP_CIRC) return FALSE;
01893    code += (code[1] << 8) + code[2];
01894    }
01895 while (*code == OP_ALT);
01896 return TRUE;
01897 }
01898 
01899 
01900 
01901 
01902 
01903 
01904 
01905 
01906 
01907 
01908 
01909 
01910 
01911 
01912 
01913 
01914 
01915 
01916 
01917 
01918 static int
01919 find_firstchar(const uschar *code, int *options)
01920 {
01921 register int c = -1;
01922 do {
01923    int d;
01924    const uschar *scode = first_significant_code(code + 3, options,
01925      PCRE_CASELESS, TRUE);
01926    register int op = *scode;
01927 
01928    if (op >= OP_BRA) op = OP_BRA;
01929 
01930    switch(op)
01931      {
01932      default:
01933      return -1;
01934 
01935      case OP_BRA:
01936      case OP_ASSERT:
01937      case OP_ONCE:
01938      case OP_COND:
01939      if ((d = find_firstchar(scode, options)) < 0) return -1;
01940      if (c < 0) c = d; else if (c != d) return -1;
01941      break;
01942 
01943      case OP_EXACT:       
01944      scode++;
01945 
01946      case OP_CHARS:       
01947      scode++;
01948 
01949      case OP_PLUS:
01950      case OP_MINPLUS:
01951      if (c < 0) c = scode[1]; else if (c != scode[1]) return -1;
01952      break;
01953      }
01954 
01955    code += (code[1] << 8) + code[2];
01956    }
01957 while (*code == OP_ALT);
01958 return c;
01959 }
01960 
01961 
01962 
01963 
01964 
01965 
01966 
01967 
01968 
01969 
01970 
01971 
01972 
01973 
01974 
01975 
01976 
01977 
01978 
01979 
01980 
01981 
01982 
01983 pcre *
01984 vmdpcre_compile(const char *pattern, int options, const char **errorptr,
01985   int *erroroffset, const unsigned char *tables)
01986 {
01987 real_pcre *re;
01988 int length = 3;      
01989 int runlength;
01990 int c, size;
01991 int bracount = 0;
01992 int top_backref = 0;
01993 int branch_extra = 0;
01994 int branch_newextra;
01995 unsigned int brastackptr = 0;
01996 uschar *code;
01997 const uschar *ptr;
01998 compile_data compile_block;
01999 int brastack[BRASTACK_SIZE];
02000 uschar bralenstack[BRASTACK_SIZE];
02001 
02002 #ifdef DEBUG
02003 uschar *code_base, *code_end;
02004 #endif
02005 
02006 
02007 
02008 
02009 if (errorptr == NULL) return NULL;
02010 *errorptr = NULL;
02011 
02012 
02013 
02014 if (erroroffset == NULL)
02015   {
02016   *errorptr = ERR16;
02017   return NULL;
02018   }
02019 *erroroffset = 0;
02020 
02021 if ((options & ~PUBLIC_OPTIONS) != 0)
02022   {
02023   *errorptr = ERR17;
02024   return NULL;
02025   }
02026 
02027 
02028 
02029 if (tables == NULL) tables = pcre_default_tables;
02030 compile_block.lcc = tables + lcc_offset;
02031 compile_block.fcc = tables + fcc_offset;
02032 compile_block.cbits = tables + cbits_offset;
02033 compile_block.ctypes = tables + ctypes_offset;
02034 
02035 
02036 
02037 DPRINTF(("------------------------------------------------------------------\n"));
02038 DPRINTF(("%s\n", pattern));
02039 
02040 
02041 
02042 
02043 
02044 
02045 
02046 
02047 ptr = (const uschar *)(pattern - 1);
02048 while ((c = *(++ptr)) != 0)
02049   {
02050   int min, max;
02051   int class_charcount;
02052 
02053   if ((options & PCRE_EXTENDED) != 0)
02054     {
02055     if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
02056     if (c == '#')
02057       {
02058       while ((c = *(++ptr)) != 0 && c != '\n');
02059       continue;
02060       }
02061     }
02062 
02063   switch(c)
02064     {
02065     
02066 
02067 
02068 
02069 
02070     case '\\':
02071       {
02072       const uschar *save_ptr = ptr;
02073       c = check_escape(&ptr, errorptr, bracount, options, FALSE, &compile_block);
02074       if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
02075       if (c >= 0)
02076         {
02077         ptr = save_ptr;
02078         c = '\\';
02079         goto NORMAL_CHAR;
02080         }
02081       }
02082     length++;
02083 
02084     
02085 
02086 
02087 
02088     if (c <= -ESC_REF)
02089       {
02090       int refnum = -c - ESC_REF;
02091       if (refnum > top_backref) top_backref = refnum;
02092       length++;   
02093       if (ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
02094         {
02095         ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block);
02096         if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
02097         if ((min == 0 && (max == 1 || max == -1)) ||
02098           (min == 1 && max == -1))
02099             length++;
02100         else length += 5;
02101         if (ptr[1] == '?') ptr++;
02102         }
02103       }
02104     continue;
02105 
02106     case '^':
02107     case '.':
02108     case '$':
02109     case '*':     
02110     case '+':     
02111     case '?':
02112     length++;
02113     continue;
02114 
02115     
02116 
02117 
02118     case '{':
02119     if (!is_counted_repeat(ptr+1, &compile_block)) goto NORMAL_CHAR;
02120     ptr = read_repeat_counts(ptr+1, &min, &max, errorptr, &compile_block);
02121     if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
02122     if ((min == 0 && (max == 1 || max == -1)) ||
02123       (min == 1 && max == -1))
02124         length++;
02125     else
02126       {
02127       length--;   
02128       if (min == 1) length++; else if (min > 0) length += 4;
02129       if (max > 0) length += 4; else length += 2;
02130       }
02131     if (ptr[1] == '?') ptr++;
02132     continue;
02133 
02134     
02135 
02136 
02137 
02138 
02139     case '|':
02140     length += 3 + branch_extra;
02141     continue;
02142 
02143     
02144 
02145 
02146 
02147 
02148     case '[':
02149     class_charcount = 0;
02150     if (*(++ptr) == '^') ptr++;
02151     do
02152       {
02153       if (*ptr == '\\')
02154         {
02155         int ch = check_escape(&ptr, errorptr, bracount, options, TRUE,
02156           &compile_block);
02157         if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
02158         if (-ch == ESC_b) class_charcount++; else class_charcount = 10;
02159         }
02160       else class_charcount++;
02161       ptr++;
02162       }
02163     while (*ptr != 0 && *ptr != ']');
02164 
02165     
02166 
02167     if (class_charcount == 1) length += 3; else
02168       {
02169       length += 33;
02170 
02171       
02172 
02173       if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
02174         {
02175         ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block);
02176         if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
02177         if ((min == 0 && (max == 1 || max == -1)) ||
02178           (min == 1 && max == -1))
02179             length++;
02180         else length += 5;
02181         if (ptr[1] == '?') ptr++;
02182         }
02183       }
02184     continue;
02185 
02186     
02187 
02188     case '(':
02189     branch_newextra = 0;
02190 
02191     
02192 
02193     if (ptr[1] == '?')
02194       {
02195       int set, unset;
02196       int *optset;
02197 
02198       switch (c = ptr[2])
02199         {
02200         
02201         case '#':
02202         ptr += 3;
02203         while (*ptr != 0 && *ptr != ')') ptr++;
02204         if (*ptr == 0)
02205           {
02206           *errorptr = ERR18;
02207           goto PCRE_ERROR_RETURN;
02208           }
02209         continue;
02210 
02211         
02212 
02213 
02214 
02215 
02216         case ':':
02217         case '=':
02218         case '!':
02219         case '>':
02220         ptr += 2;
02221         break;
02222 
02223         
02224 
02225         case '<':
02226         if (ptr[3] == '=' || ptr[3] == '!')
02227           {
02228           ptr += 3;
02229           branch_newextra = 3;
02230           length += 3;         
02231           break;
02232           }
02233         *errorptr = ERR24;
02234         goto PCRE_ERROR_RETURN;
02235 
02236         
02237 
02238 
02239 
02240         case '(':
02241         if ((compile_block.ctypes[ptr[3]] & ctype_digit) != 0)
02242           {
02243           ptr += 4;
02244           length += 2;
02245           while ((compile_block.ctypes[*ptr] & ctype_digit) != 0) ptr++;
02246           if (*ptr != ')')
02247             {
02248             *errorptr = ERR26;
02249             goto PCRE_ERROR_RETURN;
02250             }
02251           }
02252         else   
02253           {
02254           ptr++;   
02255 
02256           if (ptr[2] != '?' || strchr("=!<", ptr[3]) == NULL)
02257             {
02258             ptr += 2;    
02259             *errorptr = ERR28;
02260             goto PCRE_ERROR_RETURN;
02261             }
02262           }
02263         break;
02264 
02265         
02266 
02267 
02268 
02269 
02270         default:
02271         set = unset = 0;
02272         optset = &set;
02273         ptr += 2;
02274 
02275         for (;; ptr++)
02276           {
02277           c = *ptr;
02278           switch (c)
02279             {
02280             case 'i':
02281             *optset |= PCRE_CASELESS;
02282             continue;
02283 
02284             case 'm':
02285             *optset |= PCRE_MULTILINE;
02286             continue;
02287 
02288             case 's':
02289             *optset |= PCRE_DOTALL;
02290             continue;
02291 
02292             case 'x':
02293             *optset |= PCRE_EXTENDED;
02294             continue;
02295 
02296             case 'X':
02297             *optset |= PCRE_EXTRA;
02298             continue;
02299 
02300             case 'U':
02301             *optset |= PCRE_UNGREEDY;
02302             continue;
02303 
02304             case '-':
02305             optset = &unset;
02306             continue;
02307 
02308             
02309 
02310 
02311 
02312 
02313             case ')':
02314             if (brastackptr == 0)
02315               {
02316               options = (options | set) & (~unset);
02317               set = unset = 0;     
02318               }
02319             
02320 
02321             
02322 
02323 
02324 
02325 
02326 
02327 
02328 
02329 
02330 
02331 
02332             case ':':
02333             if (((set|unset) & PCRE_IMS) != 0)
02334               {
02335               length += 4;
02336               branch_newextra = 2;
02337               }
02338             goto END_OPTIONS;
02339 
02340             
02341 
02342             default:
02343             *errorptr = ERR12;
02344             goto PCRE_ERROR_RETURN;
02345             }
02346           }
02347 
02348         
02349 
02350 
02351 
02352 
02353 
02354         END_OPTIONS:
02355         if (c == ')')
02356           {
02357           if (branch_newextra == 2 && (branch_extra == 0 || branch_extra == 3))
02358             branch_extra += branch_newextra;
02359           continue;
02360           }
02361 
02362         
02363 
02364         }
02365       }
02366 
02367     
02368 
02369 
02370     else bracount++;
02371 
02372     
02373 
02374 
02375 
02376 
02377 
02378     if (brastackptr >= sizeof(brastack)/sizeof(int))
02379       {
02380       *errorptr = ERR19;
02381       goto PCRE_ERROR_RETURN;
02382       }
02383 
02384     bralenstack[brastackptr] = branch_extra;
02385     branch_extra = branch_newextra;
02386 
02387     brastack[brastackptr++] = length;
02388     length += 3;
02389     continue;
02390 
02391     
02392 
02393 
02394 
02395 
02396 
02397     case ')':
02398     length += 3;
02399       {
02400       int minval = 1;
02401       int maxval = 1;
02402       int duplength;
02403 
02404       if (brastackptr > 0)
02405         {
02406         duplength = length - brastack[--brastackptr];
02407         branch_extra = bralenstack[brastackptr];
02408         }
02409       else duplength = 0;
02410 
02411       
02412 
02413 
02414       if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2, &compile_block))
02415         {
02416         ptr = read_repeat_counts(ptr+2, &minval, &maxval, errorptr,
02417           &compile_block);
02418         if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
02419         }
02420       else if (c == '*') { minval = 0; maxval = -1; ptr++; }
02421       else if (c == '+') { maxval = -1; ptr++; }
02422       else if (c == '?') { minval = 0; ptr++; }
02423 
02424       
02425 
02426 
02427 
02428 
02429       if (minval == 0)
02430         {
02431         length++;
02432         if (maxval > 0) length += (maxval - 1) * (duplength + 7);
02433         }
02434 
02435       
02436 
02437 
02438 
02439 
02440 
02441       else
02442         {
02443         length += (minval - 1) * duplength;
02444         if (maxval > minval)   
02445           length += (maxval - minval) * (duplength + 7) - 6;
02446         }
02447       }
02448     continue;
02449 
02450     
02451 
02452 
02453 
02454 
02455     NORMAL_CHAR:
02456     default:
02457     length += 2;
02458     runlength = 0;
02459     do
02460       {
02461       if ((options & PCRE_EXTENDED) != 0)
02462         {
02463         if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
02464         if (c == '#')
02465           {
02466           while ((c = *(++ptr)) != 0 && c != '\n');
02467           continue;
02468           }
02469         }
02470 
02471       
02472 
02473 
02474       if (c == '\\')
02475         {
02476         const uschar *saveptr = ptr;
02477         c = check_escape(&ptr, errorptr, bracount, options, FALSE,
02478           &compile_block);
02479         if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
02480         if (c < 0) { ptr = saveptr; break; }
02481         }
02482 
02483       
02484 
02485       runlength++;
02486       }
02487 
02488     
02489 
02490     while (runlength < 255 &&
02491       (compile_block.ctypes[c = *(++ptr)] & ctype_meta) == 0);
02492 
02493     ptr--;
02494     length += runlength;
02495     continue;
02496     }
02497   }
02498 
02499 length += 4;    
02500 
02501 if (length > 65539)
02502   {
02503   *errorptr = ERR20;
02504   return NULL;
02505   }
02506 
02507 
02508 
02509 
02510 
02511 
02512 
02513 size = length + offsetof(real_pcre, code[0]);
02514 re = (real_pcre *)(vmdpcre_malloc)(size);
02515 
02516 if (re == NULL)
02517   {
02518   *errorptr = ERR21;
02519   return NULL;
02520   }
02521 
02522 
02523 
02524 re->magic_number = MAGIC_NUMBER;
02525 re->options = options;
02526 re->tables = tables;
02527 
02528 
02529 
02530 
02531 
02532 ptr = (const uschar *)pattern;
02533 code = re->code;
02534 *code = OP_BRA;
02535 bracount = 0;
02536 (void)compile_regex(options, -1, &bracount, &code, &ptr, errorptr, FALSE, -1,
02537   &compile_block);
02538 re->top_bracket = bracount;
02539 re->top_backref = top_backref;
02540 
02541 
02542 
02543 if (*errorptr == NULL && *ptr != 0) *errorptr = ERR22;
02544 
02545 
02546 
02547 
02548 *code++ = OP_END;
02549 
02550 #ifndef DEBUG
02551 if (code - re->code > length) *errorptr = ERR23;
02552 #endif
02553 
02554 
02555 
02556 
02557 if (top_backref > re->top_bracket) *errorptr = ERR15;
02558 
02559 
02560 
02561 if (*errorptr != NULL)
02562   {
02563   (vmdpcre_free)(re);
02564   PCRE_ERROR_RETURN:
02565   *erroroffset = ptr - (const uschar *)pattern;
02566   return NULL;
02567   }
02568 
02569 
02570 
02571 
02572 
02573 
02574 
02575 
02576 
02577 
02578 
02579 if ((options & PCRE_ANCHORED) == 0)
02580   {
02581   int temp_options = options;
02582   if (is_anchored(re->code, &temp_options))
02583     re->options |= PCRE_ANCHORED;
02584   else
02585     {
02586     int ch = find_firstchar(re->code, &temp_options);
02587     if (ch >= 0)
02588       {
02589       re->first_char = ch;
02590       re->options |= PCRE_FIRSTSET;
02591       }
02592     else if (is_startline(re->code))
02593       re->options |= PCRE_STARTLINE;
02594     }
02595   }
02596 
02597 
02598 
02599 #ifdef DEBUG
02600 
02601 printf("Length = %d top_bracket = %d top_backref = %d\n",
02602   length, re->top_bracket, re->top_backref);
02603 
02604 if (re->options != 0)
02605   {
02606   printf("%s%s%s%s%s%s%s%s\n",
02607     ((re->options & PCRE_ANCHORED) != 0)? "anchored " : "",
02608     ((re->options & PCRE_CASELESS) != 0)? "caseless " : "",
02609     ((re->options & PCRE_EXTENDED) != 0)? "extended " : "",
02610     ((re->options & PCRE_MULTILINE) != 0)? "multiline " : "",
02611     ((re->options & PCRE_DOTALL) != 0)? "dotall " : "",
02612     ((re->options & PCRE_DOLLAR_ENDONLY) != 0)? "endonly " : "",
02613     ((re->options & PCRE_EXTRA) != 0)? "extra " : "",
02614     ((re->options & PCRE_UNGREEDY) != 0)? "ungreedy " : "");
02615   }
02616 
02617 if ((re->options & PCRE_FIRSTSET) != 0)
02618   {
02619   if (isprint(re->first_char)) printf("First char = %c\n", re->first_char);
02620     else printf("First char = \\x%02x\n", re->first_char);
02621   }
02622 
02623 code_end = code;
02624 code_base = code = re->code;
02625 
02626 while (code < code_end)
02627   {
02628   int charlength;
02629 
02630   printf("%3d ", code - code_base);
02631 
02632   if (*code >= OP_BRA)
02633     {
02634     printf("%3d Bra %d", (code[1] << 8) + code[2], *code - OP_BRA);
02635     code += 2;
02636     }
02637 
02638   else switch(*code)
02639     {
02640     case OP_OPT:
02641     printf(" %.2x %s", code[1], OP_names[*code]);
02642     code++;
02643     break;
02644 
02645     case OP_COND:
02646     printf("%3d Cond", (code[1] << 8) + code[2]);
02647     code += 2;
02648     break;
02649 
02650     case OP_CREF:
02651     printf(" %.2d %s", code[1], OP_names[*code]);
02652     code++;
02653     break;
02654 
02655     case OP_CHARS:
02656     charlength = *(++code);
02657     printf("%3d ", charlength);
02658     while (charlength-- > 0)
02659       if (isprint(c = *(++code))) printf("%c", c); else printf("\\x%02x", c);
02660     break;
02661 
02662     case OP_KETRMAX:
02663     case OP_KETRMIN:
02664     case OP_ALT:
02665     case OP_KET:
02666     case OP_ASSERT:
02667     case OP_ASSERT_NOT:
02668     case OP_ASSERTBACK:
02669     case OP_ASSERTBACK_NOT:
02670     case OP_ONCE:
02671     printf("%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
02672     code += 2;
02673     break;
02674 
02675     case OP_REVERSE:
02676     printf("%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
02677     code += 2;
02678     break;
02679 
02680     case OP_STAR:
02681     case OP_MINSTAR:
02682     case OP_PLUS:
02683     case OP_MINPLUS:
02684     case OP_QUERY:
02685     case OP_MINQUERY:
02686     case OP_TYPESTAR:
02687     case OP_TYPEMINSTAR:
02688     case OP_TYPEPLUS:
02689     case OP_TYPEMINPLUS:
02690     case OP_TYPEQUERY:
02691     case OP_TYPEMINQUERY:
02692     if (*code >= OP_TYPESTAR)
02693       printf("    %s", OP_names[code[1]]);
02694     else if (isprint(c = code[1])) printf("    %c", c);
02695       else printf("    \\x%02x", c);
02696     printf("%s", OP_names[*code++]);
02697     break;
02698 
02699     case OP_EXACT:
02700     case OP_UPTO:
02701     case OP_MINUPTO:
02702     if (isprint(c = code[3])) printf("    %c{", c);
02703       else printf("    \\x%02x{", c);
02704     if (*code != OP_EXACT) printf("0,");
02705     printf("%d}", (code[1] << 8) + code[2]);
02706     if (*code == OP_MINUPTO) printf("?");
02707     code += 3;
02708     break;
02709 
02710     case OP_TYPEEXACT:
02711     case OP_TYPEUPTO:
02712     case OP_TYPEMINUPTO:
02713     printf("    %s{", OP_names[code[3]]);
02714     if (*code != OP_TYPEEXACT) printf(",");
02715     printf("%d}", (code[1] << 8) + code[2]);
02716     if (*code == OP_TYPEMINUPTO) printf("?");
02717     code += 3;
02718     break;
02719 
02720     case OP_NOT:
02721     if (isprint(c = *(++code))) printf("    [^%c]", c);
02722       else printf("    [^\\x%02x]", c);
02723     break;
02724 
02725     case OP_NOTSTAR:
02726     case OP_NOTMINSTAR:
02727     case OP_NOTPLUS:
02728     case OP_NOTMINPLUS:
02729     case OP_NOTQUERY:
02730     case OP_NOTMINQUERY:
02731     if (isprint(c = code[1])) printf("    [^%c]", c);
02732       else printf("    [^\\x%02x]", c);
02733     printf("%s", OP_names[*code++]);
02734     break;
02735 
02736     case OP_NOTEXACT:
02737     case OP_NOTUPTO:
02738     case OP_NOTMINUPTO:
02739     if (isprint(c = code[3])) printf("    [^%c]{", c);
02740       else printf("    [^\\x%02x]{", c);
02741     if (*code != OP_NOTEXACT) printf(",");
02742     printf("%d}", (code[1] << 8) + code[2]);
02743     if (*code == OP_NOTMINUPTO) printf("?");
02744     code += 3;
02745     break;
02746 
02747     case OP_REF:
02748     printf("    \\%d", *(++code));
02749     code ++;
02750     goto CLASS_REF_REPEAT;
02751 
02752     case OP_CLASS:
02753       {
02754       int i, min, max;
02755       code++;
02756       printf("    [");
02757 
02758       for (i = 0; i < 256; i++)
02759         {
02760         if ((code[i/8] & (1 << (i&7))) != 0)
02761           {
02762           int j;
02763           for (j = i+1; j < 256; j++)
02764             if ((code[j/8] & (1 << (j&7))) == 0) break;
02765           if (i == '-' || i == ']') printf("\\");
02766           if (isprint(i)) printf("%c", i); else printf("\\x%02x", i);
02767           if (--j > i)
02768             {
02769             printf("-");
02770             if (j == '-' || j == ']') printf("\\");
02771             if (isprint(j)) printf("%c", j); else printf("\\x%02x", j);
02772             }
02773           i = j;
02774           }
02775         }
02776       printf("]");
02777       code += 32;
02778 
02779       CLASS_REF_REPEAT:
02780 
02781       switch(*code)
02782         {
02783         case OP_CRSTAR:
02784         case OP_CRMINSTAR:
02785         case OP_CRPLUS:
02786         case OP_CRMINPLUS:
02787         case OP_CRQUERY:
02788         case OP_CRMINQUERY:
02789         printf("%s", OP_names[*code]);
02790         break;
02791 
02792         case OP_CRRANGE:
02793         case OP_CRMINRANGE:
02794         min = (code[1] << 8) + code[2];
02795         max = (code[3] << 8) + code[4];
02796         if (max == 0) printf("{%d,}", min);
02797         else printf("{%d,%d}", min, max);
02798         if (*code == OP_CRMINRANGE) printf("?");
02799         code += 4;
02800         break;
02801 
02802         default:
02803         code--;
02804         }
02805       }
02806     break;
02807 
02808     
02809 
02810     default:
02811     printf("    %s", OP_names[*code]);
02812     break;
02813     }
02814 
02815   code++;
02816   printf("\n");
02817   }
02818 printf("------------------------------------------------------------------\n");
02819 
02820 
02821 
02822 
02823 if (code - re->code > length)
02824   {
02825   *errorptr = ERR23;
02826   (vmdpcre_free)(re);
02827   *erroroffset = ptr - (uschar *)pattern;
02828   return NULL;
02829   }
02830 #endif
02831 
02832 return (pcre *)re;
02833 }
02834 
02835 
02836 
02837 
02838 
02839 
02840 
02841 
02842 
02843 
02844 
02845 
02846 
02847 
02848 
02849 
02850 
02851 
02852 
02853 
02854 static BOOL
02855 match_ref(int offset, register const uschar *eptr, int length, match_data *md,
02856   int ims)
02857 {
02858 const uschar *p = md->start_subject + md->offset_vector[offset];
02859 
02860 #ifdef DEBUG
02861 if (eptr >= md->end_subject)
02862   printf("matching subject <null>");
02863 else
02864   {
02865   printf("matching subject ");
02866   pchars(eptr, length, TRUE, md);
02867   }
02868 printf(" against backref ");
02869 pchars(p, length, FALSE, md);
02870 printf("\n");
02871 #endif
02872 
02873 
02874 
02875 if (length > md->end_subject - eptr) return FALSE;
02876 
02877 
02878 
02879 if ((ims & PCRE_CASELESS) != 0)
02880   {
02881   while (length-- > 0)
02882     if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
02883   }
02884 else
02885   { while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
02886 
02887 return TRUE;
02888 }
02889 
02890 
02891 
02892 
02893 
02894 
02895 
02896 
02897 
02898 
02899 
02900 
02901 
02902 
02903 
02904 
02905 
02906 
02907 
02908 
02909 
02910 
02911 
02912 
02913 static BOOL
02914 match(register const uschar *eptr, register const uschar *ecode,
02915   int offset_top, match_data *md, int ims, BOOL condassert, const uschar *eptrb)
02916 {
02917 int original_ims = ims;   
02918 
02919 for (;;)
02920   {
02921   int op = (int)*ecode;
02922   int min, max, ctype;
02923   register int i;
02924   register int c;
02925   BOOL minimize = FALSE;
02926 
02927   
02928 
02929 
02930 
02931 
02932 
02933 
02934 
02935 
02936 
02937 
02938 
02939 
02940 
02941   if (op > OP_BRA)
02942     {
02943     int number = op - OP_BRA;
02944     int offset = number << 1;
02945 
02946 #ifdef DEBUG
02947     printf("start bracket %d subject=", number);
02948     pchars(eptr, 16, TRUE, md);
02949     printf("\n");
02950 #endif
02951 
02952     if (offset < md->offset_max)
02953       {
02954       int save_offset1 = md->offset_vector[offset];
02955       int save_offset2 = md->offset_vector[offset+1];
02956       int save_offset3 = md->offset_vector[md->offset_end - number];
02957 
02958       DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
02959       md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
02960 
02961       do
02962         {
02963         if (match(eptr, ecode+3, offset_top, md, ims, FALSE, eptr)) return TRUE;
02964         ecode += (ecode[1] << 8) + ecode[2];
02965         }
02966       while (*ecode == OP_ALT);
02967 
02968       DPRINTF(("bracket %d failed\n", number));
02969 
02970       md->offset_vector[offset] = save_offset1;
02971       md->offset_vector[offset+1] = save_offset2;
02972       md->offset_vector[md->offset_end - number] = save_offset3;
02973       return FALSE;
02974       }
02975 
02976     
02977 
02978     else op = OP_BRA;
02979     }
02980 
02981   
02982 
02983   switch(op)
02984     {
02985     case OP_BRA:     
02986     DPRINTF(("start bracket 0\n"));
02987     do
02988       {
02989       if (match(eptr, ecode+3, offset_top, md, ims, FALSE, eptr)) return TRUE;
02990       ecode += (ecode[1] << 8) + ecode[2];
02991       }
02992     while (*ecode == OP_ALT);
02993     DPRINTF(("bracket 0 failed\n"));
02994     return FALSE;
02995 
02996     
02997 
02998 
02999 
03000 
03001     case OP_COND:
03002     if (ecode[3] == OP_CREF)         
03003       {
03004       int offset = ecode[4] << 1;    
03005       return match(eptr,
03006         ecode + ((offset < offset_top && md->offset_vector[offset] >= 0)?
03007           5 : 3 + (ecode[1] << 8) + ecode[2]),
03008         offset_top, md, ims, FALSE, eptr);
03009       }
03010 
03011     
03012 
03013 
03014     else
03015       {
03016       if (match(eptr, ecode+3, offset_top, md, ims, TRUE, NULL))
03017         {
03018         ecode += 3 + (ecode[4] << 8) + ecode[5];
03019         while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2];
03020         }
03021       else ecode += (ecode[1] << 8) + ecode[2];
03022       return match(eptr, ecode+3, offset_top, md, ims, FALSE, eptr);
03023       }
03024     
03025 
03026     
03027 
03028     case OP_CREF:
03029     ecode += 2;
03030     break;
03031 
03032     
03033 
03034     case OP_END:
03035     md->end_match_ptr = eptr;          
03036     md->end_offset_top = offset_top;   
03037     return TRUE;
03038 
03039     
03040 
03041     case OP_OPT:
03042     ims = ecode[1];
03043     ecode += 2;
03044     DPRINTF(("ims set to %02x\n", ims));
03045     break;
03046 
03047     
03048 
03049 
03050 
03051 
03052 
03053     case OP_ASSERT:
03054     case OP_ASSERTBACK:
03055     do
03056       {
03057       if (match(eptr, ecode+3, offset_top, md, ims, FALSE, NULL)) break;
03058       ecode += (ecode[1] << 8) + ecode[2];
03059       }
03060     while (*ecode == OP_ALT);
03061     if (*ecode == OP_KET) return FALSE;
03062 
03063     
03064 
03065     if (condassert) return TRUE;
03066 
03067     
03068 
03069 
03070     do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
03071     ecode += 3;
03072     offset_top = md->end_offset_top;
03073     continue;
03074 
03075     
03076 
03077     case OP_ASSERT_NOT:
03078     case OP_ASSERTBACK_NOT:
03079     do
03080       {
03081       if (match(eptr, ecode+3, offset_top, md, ims, FALSE, NULL)) return FALSE;
03082       ecode += (ecode[1] << 8) + ecode[2];
03083       }
03084     while (*ecode == OP_ALT);
03085 
03086     if (condassert) return TRUE;
03087     ecode += 3;
03088     continue;
03089 
03090     
03091 
03092 
03093 
03094     case OP_REVERSE:
03095     eptr -= (ecode[1] << 8) + ecode[2];
03096     if (eptr < md->start_subject) return FALSE;
03097     ecode += 3;
03098     break;
03099 
03100 
03101     
03102 
03103 
03104 
03105 
03106 
03107 
03108     case OP_ONCE:
03109       {
03110       const uschar *prev = ecode;
03111 
03112       do
03113         {
03114         if (match(eptr, ecode+3, offset_top, md, ims, FALSE, eptr)) break;
03115         ecode += (ecode[1] << 8) + ecode[2];
03116         }
03117       while (*ecode == OP_ALT);
03118 
03119       
03120 
03121       if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE;
03122 
03123       
03124 
03125 
03126       do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
03127 
03128       offset_top = md->end_offset_top;
03129       eptr = md->end_match_ptr;
03130 
03131       
03132 
03133 
03134 
03135 
03136 
03137       if (*ecode == OP_KET || eptr == eptrb)
03138         {
03139         ecode += 3;
03140         break;
03141         }
03142 
03143       
03144 
03145 
03146 
03147 
03148       if (ecode[3] == OP_OPT)
03149         {
03150         ims = (ims & ~PCRE_IMS) | ecode[4];
03151         DPRINTF(("ims set to %02x at group repeat\n", ims));
03152         }
03153 
03154       if (*ecode == OP_KETRMIN)
03155         {
03156         if (match(eptr, ecode+3, offset_top, md, ims, FALSE, eptr) ||
03157             match(eptr, prev, offset_top, md, ims, FALSE, eptr)) return TRUE;
03158         }
03159       else  
03160         {
03161         if (match(eptr, prev, offset_top, md, ims, FALSE, eptr) ||
03162             match(eptr, ecode+3, offset_top, md, ims, FALSE, eptr)) return TRUE;
03163         }
03164       }
03165     return FALSE;
03166 
03167     
03168 
03169 
03170     case OP_ALT:
03171     do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
03172     break;
03173 
03174     
03175 
03176 
03177 
03178 
03179 
03180     case OP_BRAZERO:
03181       {
03182       const uschar *next = ecode+1;
03183       if (match(eptr, next, offset_top, md, ims, FALSE, eptr)) return TRUE;
03184       do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
03185       ecode = next + 3;
03186       }
03187     break;
03188 
03189     case OP_BRAMINZERO:
03190       {
03191       const uschar *next = ecode+1;
03192       do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
03193       if (match(eptr, next+3, offset_top, md, ims, FALSE, eptr)) return TRUE;
03194       ecode++;
03195       }
03196     break;
03197 
03198     
03199 
03200 
03201 
03202 
03203     case OP_KET:
03204     case OP_KETRMIN:
03205     case OP_KETRMAX:
03206       {
03207       const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
03208 
03209       if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
03210           *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
03211           *prev == OP_ONCE)
03212         {
03213         md->end_match_ptr = eptr;      
03214         md->end_offset_top = offset_top;
03215         return TRUE;
03216         }
03217 
03218       
03219 
03220 
03221 
03222       if (*prev != OP_COND)
03223         {
03224         int number = *prev - OP_BRA;
03225         int offset = number << 1;
03226 
03227         DPRINTF(("end bracket %d\n", number));
03228 
03229         if (number > 0)
03230           {
03231           if (offset >= md->offset_max) md->offset_overflow = TRUE; else
03232             {
03233             md->offset_vector[offset] =
03234               md->offset_vector[md->offset_end - number];
03235             md->offset_vector[offset+1] = eptr - md->start_subject;
03236             if (offset_top <= offset) offset_top = offset + 2;
03237             }
03238           }
03239         }
03240 
03241       
03242 
03243 
03244       ims = original_ims;
03245       DPRINTF(("ims reset to %02x\n", ims));
03246 
03247       
03248 
03249 
03250 
03251 
03252 
03253       if (*ecode == OP_KET || eptr == eptrb)
03254         {
03255         ecode += 3;
03256         break;
03257         }
03258 
03259       
03260 
03261 
03262       if (*ecode == OP_KETRMIN)
03263         {
03264         if (match(eptr, ecode+3, offset_top, md, ims, FALSE, eptr) ||
03265             match(eptr, prev, offset_top, md, ims, FALSE, eptr)) return TRUE;
03266         }
03267       else  
03268         {
03269         if (match(eptr, prev, offset_top, md, ims, FALSE, eptr) ||
03270             match(eptr, ecode+3, offset_top, md, ims, FALSE, eptr)) return TRUE;
03271         }
03272       }
03273     return FALSE;
03274 
03275     
03276 
03277     case OP_CIRC:
03278     if (md->notbol && eptr == md->start_subject) return FALSE;
03279     if ((ims & PCRE_MULTILINE) != 0)
03280       {
03281       if (eptr != md->start_subject && eptr[-1] != '\n') return FALSE;
03282       ecode++;
03283       break;
03284       }
03285     
03286 
03287     
03288 
03289     case OP_SOD:
03290     if (eptr != md->start_subject) return FALSE;
03291     ecode++;
03292     break;
03293 
03294     
03295 
03296 
03297     case OP_DOLL:
03298     if ((ims & PCRE_MULTILINE) != 0)
03299       {
03300       if (eptr < md->end_subject) { if (*eptr != '\n') return FALSE; }
03301         else { if (md->noteol) return FALSE; }
03302       ecode++;
03303       break;
03304       }
03305     else
03306       {
03307       if (md->noteol) return FALSE;
03308       if (!md->endonly)
03309         {
03310         if (eptr < md->end_subject - 1 ||
03311            (eptr == md->end_subject - 1 && *eptr != '\n')) return FALSE;
03312 
03313         ecode++;
03314         break;
03315         }
03316       }
03317     
03318 
03319     
03320 
03321     case OP_EOD:
03322     if (eptr < md->end_subject) return FALSE;
03323     ecode++;
03324     break;
03325 
03326     
03327 
03328     case OP_EODN:
03329     if (eptr < md->end_subject - 1 ||
03330        (eptr == md->end_subject - 1 && *eptr != '\n')) return FALSE;
03331     ecode++;
03332     break;
03333 
03334     
03335 
03336     case OP_NOT_WORD_BOUNDARY:
03337     case OP_WORD_BOUNDARY:
03338       {
03339       BOOL prev_is_word = (eptr != md->start_subject) &&
03340         ((md->ctypes[eptr[-1]] & ctype_word) != 0);
03341       BOOL cur_is_word = (eptr < md->end_subject) &&
03342         ((md->ctypes[*eptr] & ctype_word) != 0);
03343       if ((*ecode++ == OP_WORD_BOUNDARY)?
03344            cur_is_word == prev_is_word : cur_is_word != prev_is_word)
03345         return FALSE;
03346       }
03347     break;
03348 
03349     
03350 
03351     case OP_ANY:
03352     if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == '\n')
03353       return FALSE;
03354     if (eptr++ >= md->end_subject) return FALSE;
03355     ecode++;
03356     break;
03357 
03358     case OP_NOT_DIGIT:
03359     if (eptr >= md->end_subject ||
03360        (md->ctypes[*eptr++] & ctype_digit) != 0)
03361       return FALSE;
03362     ecode++;
03363     break;
03364 
03365     case OP_DIGIT:
03366     if (eptr >= md->end_subject ||
03367        (md->ctypes[*eptr++] & ctype_digit) == 0)
03368       return FALSE;
03369     ecode++;
03370     break;
03371 
03372     case OP_NOT_WHITESPACE:
03373     if (eptr >= md->end_subject ||
03374        (md->ctypes[*eptr++] & ctype_space) != 0)
03375       return FALSE;
03376     ecode++;
03377     break;
03378 
03379     case OP_WHITESPACE:
03380     if (eptr >= md->end_subject ||
03381        (md->ctypes[*eptr++] & ctype_space) == 0)
03382       return FALSE;
03383     ecode++;
03384     break;
03385 
03386     case OP_NOT_WORDCHAR:
03387     if (eptr >= md->end_subject ||
03388        (md->ctypes[*eptr++] & ctype_word) != 0)
03389       return FALSE;
03390     ecode++;
03391     break;
03392 
03393     case OP_WORDCHAR:
03394     if (eptr >= md->end_subject ||
03395        (md->ctypes[*eptr++] & ctype_word) == 0)
03396       return FALSE;
03397     ecode++;
03398     break;
03399 
03400     
03401 
03402 
03403 
03404 
03405 
03406 
03407 
03408     case OP_REF:
03409       {
03410       int length;
03411       int offset = ecode[1] << 1;                
03412       ecode += 2;                                
03413 
03414       
03415 
03416 
03417 
03418 
03419       length = (offset >= offset_top || md->offset_vector[offset] < 0)?
03420         md->end_subject - eptr + 1 :
03421         md->offset_vector[offset+1] - md->offset_vector[offset];
03422 
03423       
03424 
03425       switch (*ecode)
03426         {
03427         case OP_CRSTAR:
03428         case OP_CRMINSTAR:
03429         case OP_CRPLUS:
03430         case OP_CRMINPLUS:
03431         case OP_CRQUERY:
03432         case OP_CRMINQUERY:
03433         c = *ecode++ - OP_CRSTAR;
03434         minimize = (c & 1) != 0;
03435         min = rep_min[c];                 
03436         max = rep_max[c];                 
03437         if (max == 0) max = INT_MAX;
03438         break;
03439 
03440         case OP_CRRANGE:
03441         case OP_CRMINRANGE:
03442         minimize = (*ecode == OP_CRMINRANGE);
03443         min = (ecode[1] << 8) + ecode[2];
03444         max = (ecode[3] << 8) + ecode[4];
03445         if (max == 0) max = INT_MAX;
03446         ecode += 5;
03447         break;
03448 
03449         default:               
03450         if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
03451         eptr += length;
03452         continue;              
03453         }
03454 
03455       
03456 
03457 
03458       if (length == 0) continue;
03459 
03460       
03461 
03462 
03463 
03464       for (i = 1; i <= min; i++)
03465         {
03466         if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
03467         eptr += length;
03468         }
03469 
03470       
03471 
03472 
03473       if (min == max) continue;
03474 
03475       
03476 
03477       if (minimize)
03478         {
03479         for (i = min;; i++)
03480           {
03481           if (match(eptr, ecode, offset_top, md, ims, FALSE, eptrb))
03482             return TRUE;
03483           if (i >= max || !match_ref(offset, eptr, length, md, ims))
03484             return FALSE;
03485           eptr += length;
03486           }
03487         
03488         }
03489 
03490       
03491 
03492       else
03493         {
03494         const uschar *pp = eptr;
03495         for (i = min; i < max; i++)
03496           {
03497           if (!match_ref(offset, eptr, length, md, ims)) break;
03498           eptr += length;
03499           }
03500         while (eptr >= pp)
03501           {
03502           if (match(eptr, ecode, offset_top, md, ims, FALSE, eptrb))
03503             return TRUE;
03504           eptr -= length;
03505           }
03506         return FALSE;
03507         }
03508       }
03509     
03510 
03511 
03512 
03513     
03514 
03515 
03516 
03517     case OP_CLASS:
03518       {
03519       const uschar *data = ecode + 1;  
03520       ecode += 33;                     
03521 
03522       switch (*ecode)
03523         {
03524         case OP_CRSTAR:
03525         case OP_CRMINSTAR:
03526         case OP_CRPLUS:
03527         case OP_CRMINPLUS:
03528         case OP_CRQUERY:
03529         case OP_CRMINQUERY:
03530         c = *ecode++ - OP_CRSTAR;
03531         minimize = (c & 1) != 0;
03532         min = rep_min[c];                 
03533         max = rep_max[c];                 
03534         if (max == 0) max = INT_MAX;
03535         break;
03536 
03537         case OP_CRRANGE:
03538         case OP_CRMINRANGE:
03539         minimize = (*ecode == OP_CRMINRANGE);
03540         min = (ecode[1] << 8) + ecode[2];
03541         max = (ecode[3] << 8) + ecode[4];
03542         if (max == 0) max = INT_MAX;
03543         ecode += 5;
03544         break;
03545 
03546         default:               
03547         min = max = 1;
03548         break;
03549         }
03550 
03551       
03552 
03553       for (i = 1; i <= min; i++)
03554         {
03555         if (eptr >= md->end_subject) return FALSE;
03556         c = *eptr++;
03557         if ((data[c/8] & (1 << (c&7))) != 0) continue;
03558         return FALSE;
03559         }
03560 
03561       
03562 
03563 
03564       if (min == max) continue;
03565 
03566       
03567 
03568 
03569       if (minimize)
03570         {
03571         for (i = min;; i++)
03572           {
03573           if (match(eptr, ecode, offset_top, md, ims, FALSE, eptrb))
03574             return TRUE;
03575           if (i >= max || eptr >= md->end_subject) return FALSE;
03576           c = *eptr++;
03577           if ((data[c/8] & (1 << (c&7))) != 0) continue;
03578           return FALSE;
03579           }
03580         
03581         }
03582 
03583       
03584 
03585       else
03586         {
03587         const uschar *pp = eptr;
03588         for (i = min; i < max; eptr++, i++)
03589           {
03590           if (eptr >= md->end_subject) break;
03591           c = *eptr;
03592           if ((data[c/8] & (1 << (c&7))) != 0) continue;
03593           break;
03594           }
03595 
03596         while (eptr >= pp)
03597           if (match(eptr--, ecode, offset_top, md, ims, FALSE, eptrb))
03598             return TRUE;
03599         return FALSE;
03600         }
03601       }
03602     
03603 
03604     
03605 
03606     case OP_CHARS:
03607       {
03608       register int length = ecode[1];
03609       ecode += 2;
03610 
03611 #ifdef DEBUG    
03612       if (eptr >= md->end_subject)
03613         printf("matching subject <null> against pattern ");
03614       else
03615         {
03616         printf("matching subject ");
03617         pchars(eptr, length, TRUE, md);
03618         printf(" against pattern ");
03619         }
03620       pchars(ecode, length, FALSE, md);
03621       printf("\n");
03622 #endif
03623 
03624       if (length > md->end_subject - eptr) return FALSE;
03625       if ((ims & PCRE_CASELESS) != 0)
03626         {
03627         while (length-- > 0)
03628           if (md->lcc[*ecode++] != md->lcc[*eptr++])
03629             return FALSE;
03630         }
03631       else
03632         {
03633         while (length-- > 0) if (*ecode++ != *eptr++) return FALSE;
03634         }
03635       }
03636     break;
03637 
03638     
03639 
03640     case OP_EXACT:
03641     min = max = (ecode[1] << 8) + ecode[2];
03642     ecode += 3;
03643     goto REPEATCHAR;
03644 
03645     case OP_UPTO:
03646     case OP_MINUPTO:
03647     min = 0;
03648     max = (ecode[1] << 8) + ecode[2];
03649     minimize = *ecode == OP_MINUPTO;
03650     ecode += 3;
03651     goto REPEATCHAR;
03652 
03653     case OP_STAR:
03654     case OP_MINSTAR:
03655     case OP_PLUS:
03656     case OP_MINPLUS:
03657     case OP_QUERY:
03658     case OP_MINQUERY:
03659     c = *ecode++ - OP_STAR;
03660     minimize = (c & 1) != 0;
03661     min = rep_min[c];                 
03662     max = rep_max[c];                 
03663     if (max == 0) max = INT_MAX;
03664 
03665     
03666 
03667 
03668 
03669     REPEATCHAR:
03670     if (min > md->end_subject - eptr) return FALSE;
03671     c = *ecode++;
03672 
03673     
03674 
03675 
03676 
03677 
03678 
03679 
03680 
03681     DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max,
03682       max, eptr));
03683 
03684     if ((ims & PCRE_CASELESS) != 0)
03685       {
03686       c = md->lcc[c];
03687       for (i = 1; i <= min; i++)
03688         if (c != md->lcc[*eptr++]) return FALSE;
03689       if (min == max) continue;
03690       if (minimize)
03691         {
03692         for (i = min;; i++)
03693           {
03694           if (match(eptr, ecode, offset_top, md, ims, FALSE, eptrb))
03695             return TRUE;
03696           if (i >= max || eptr >= md->end_subject ||
03697               c != md->lcc[*eptr++])
03698             return FALSE;
03699           }
03700         
03701         }
03702       else
03703         {
03704         const uschar *pp = eptr;
03705         for (i = min; i < max; i++)
03706           {
03707           if (eptr >= md->end_subject || c != md->lcc[*eptr]) break;
03708           eptr++;
03709           }
03710         while (eptr >= pp)
03711           if (match(eptr--, ecode, offset_top, md, ims, FALSE, eptrb))
03712             return TRUE;
03713         return FALSE;
03714         }
03715       
03716       }
03717 
03718     
03719 
03720     else
03721       {
03722       for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE;
03723       if (min == max) continue;
03724       if (minimize)
03725         {
03726         for (i = min;; i++)
03727           {
03728           if (match(eptr, ecode, offset_top, md, ims, FALSE, eptrb))
03729             return TRUE;
03730           if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE;
03731           }
03732         
03733         }
03734       else
03735         {
03736         const uschar *pp = eptr;
03737         for (i = min; i < max; i++)
03738           {
03739           if (eptr >= md->end_subject || c != *eptr) break;
03740           eptr++;
03741           }
03742         while (eptr >= pp)
03743          if (match(eptr--, ecode, offset_top, md, ims, FALSE, eptrb))
03744            return TRUE;
03745         return FALSE;
03746         }
03747       }
03748     
03749 
03750     
03751 
03752     case OP_NOT:
03753     if (eptr >= md->end_subject) return FALSE;
03754     ecode++;
03755     if ((ims & PCRE_CASELESS) != 0)
03756       {
03757       if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE;
03758       }
03759     else
03760       {
03761       if (*ecode++ == *eptr++) return FALSE;
03762       }
03763     break;
03764 
03765     
03766 
03767 
03768 
03769 
03770 
03771     case OP_NOTEXACT:
03772     min = max = (ecode[1] << 8) + ecode[2];
03773     ecode += 3;
03774     goto REPEATNOTCHAR;
03775 
03776     case OP_NOTUPTO:
03777     case OP_NOTMINUPTO:
03778     min = 0;
03779     max = (ecode[1] << 8) + ecode[2];
03780     minimize = *ecode == OP_NOTMINUPTO;
03781     ecode += 3;
03782     goto REPEATNOTCHAR;
03783 
03784     case OP_NOTSTAR:
03785     case OP_NOTMINSTAR:
03786     case OP_NOTPLUS:
03787     case OP_NOTMINPLUS:
03788     case OP_NOTQUERY:
03789     case OP_NOTMINQUERY:
03790     c = *ecode++ - OP_NOTSTAR;
03791     minimize = (c & 1) != 0;
03792     min = rep_min[c];                 
03793     max = rep_max[c];                 
03794     if (max == 0) max = INT_MAX;
03795 
03796     
03797 
03798 
03799 
03800     REPEATNOTCHAR:
03801     if (min > md->end_subject - eptr) return FALSE;
03802     c = *ecode++;
03803 
03804     
03805 
03806 
03807 
03808 
03809 
03810 
03811 
03812     DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
03813       max, eptr));
03814 
03815     if ((ims & PCRE_CASELESS) != 0)
03816       {
03817       c = md->lcc[c];
03818       for (i = 1; i <= min; i++)
03819         if (c == md->lcc[*eptr++]) return FALSE;
03820       if (min == max) continue;
03821       if (minimize)
03822         {
03823         for (i = min;; i++)
03824           {
03825           if (match(eptr, ecode, offset_top, md, ims, FALSE, eptrb))
03826             return TRUE;
03827           if (i >= max || eptr >= md->end_subject ||
03828               c == md->lcc[*eptr++])
03829             return FALSE;
03830           }
03831         
03832         }
03833       else
03834         {
03835         const uschar *pp = eptr;
03836         for (i = min; i < max; i++)
03837           {
03838           if (eptr >= md->end_subject || c == md->lcc[*eptr]) break;
03839           eptr++;
03840           }
03841         while (eptr >= pp)
03842           if (match(eptr--, ecode, offset_top, md, ims, FALSE, eptrb))
03843             return TRUE;
03844         return FALSE;
03845         }
03846       
03847       }
03848 
03849     
03850 
03851     else
03852       {
03853       for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE;
03854       if (min == max) continue;
03855       if (minimize)
03856         {
03857         for (i = min;; i++)
03858           {
03859           if (match(eptr, ecode, offset_top, md, ims, FALSE, eptrb))
03860             return TRUE;
03861           if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE;
03862           }
03863         
03864         }
03865       else
03866         {
03867         const uschar *pp = eptr;
03868         for (i = min; i < max; i++)
03869           {
03870           if (eptr >= md->end_subject || c == *eptr) break;
03871           eptr++;
03872           }
03873         while (eptr >= pp)
03874          if (match(eptr--, ecode, offset_top, md, ims, FALSE, eptrb))
03875            return TRUE;
03876         return FALSE;
03877         }
03878       }
03879     
03880 
03881     
03882 
03883 
03884 
03885     case OP_TYPEEXACT:
03886     min = max = (ecode[1] << 8) + ecode[2];
03887     minimize = TRUE;
03888     ecode += 3;
03889     goto REPEATTYPE;
03890 
03891     case OP_TYPEUPTO:
03892     case OP_TYPEMINUPTO:
03893     min = 0;
03894     max = (ecode[1] << 8) + ecode[2];
03895     minimize = *ecode == OP_TYPEMINUPTO;
03896     ecode += 3;
03897     goto REPEATTYPE;
03898 
03899     case OP_TYPESTAR:
03900     case OP_TYPEMINSTAR:
03901     case OP_TYPEPLUS:
03902     case OP_TYPEMINPLUS:
03903     case OP_TYPEQUERY:
03904     case OP_TYPEMINQUERY:
03905     c = *ecode++ - OP_TYPESTAR;
03906     minimize = (c & 1) != 0;
03907     min = rep_min[c];                 
03908     max = rep_max[c];                 
03909     if (max == 0) max = INT_MAX;
03910 
03911     
03912 
03913     REPEATTYPE:
03914     ctype = *ecode++;      
03915 
03916     
03917 
03918 
03919 
03920 
03921     if (min > md->end_subject - eptr) return FALSE;
03922     if (min > 0) switch(ctype)
03923       {
03924       case OP_ANY:
03925       if ((ims & PCRE_DOTALL) == 0)
03926         { for (i = 1; i <= min; i++) if (*eptr++ == '\n') return FALSE; }
03927       else eptr += min;
03928       break;
03929 
03930       case OP_NOT_DIGIT:
03931       for (i = 1; i <= min; i++)
03932         if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE;
03933       break;
03934 
03935       case OP_DIGIT:
03936       for (i = 1; i <= min; i++)
03937         if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE;
03938       break;
03939 
03940       case OP_NOT_WHITESPACE:
03941       for (i = 1; i <= min; i++)
03942         if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE;
03943       break;
03944 
03945       case OP_WHITESPACE:
03946       for (i = 1; i <= min; i++)
03947         if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE;
03948       break;
03949 
03950       case OP_NOT_WORDCHAR:
03951       for (i = 1; i <= min; i++)
03952         if ((md->ctypes[*eptr++] & ctype_word) != 0)
03953           return FALSE;
03954       break;
03955 
03956       case OP_WORDCHAR:
03957       for (i = 1; i <= min; i++)
03958         if ((md->ctypes[*eptr++] & ctype_word) == 0)
03959           return FALSE;
03960       break;
03961       }
03962 
03963     
03964 
03965     if (min == max) continue;
03966 
03967     
03968 
03969 
03970     if (minimize)
03971       {
03972       for (i = min;; i++)
03973         {
03974         if (match(eptr, ecode, offset_top, md, ims, FALSE, eptrb)) return TRUE;
03975         if (i >= max || eptr >= md->end_subject) return FALSE;
03976 
03977         c = *eptr++;
03978         switch(ctype)
03979           {
03980           case OP_ANY:
03981           if ((ims & PCRE_DOTALL) == 0 && c == '\n') return FALSE;
03982           break;
03983 
03984           case OP_NOT_DIGIT:
03985           if ((md->ctypes[c] & ctype_digit) != 0) return FALSE;
03986           break;
03987 
03988           case OP_DIGIT:
03989           if ((md->ctypes[c] & ctype_digit) == 0) return FALSE;
03990           break;
03991 
03992           case OP_NOT_WHITESPACE:
03993           if ((md->ctypes[c] & ctype_space) != 0) return FALSE;
03994           break;
03995 
03996           case OP_WHITESPACE:
03997           if  ((md->ctypes[c] & ctype_space) == 0) return FALSE;
03998           break;
03999 
04000           case OP_NOT_WORDCHAR:
04001           if ((md->ctypes[c] & ctype_word) != 0) return FALSE;
04002           break;
04003 
04004           case OP_WORDCHAR:
04005           if ((md->ctypes[c] & ctype_word) == 0) return FALSE;
04006           break;
04007           }
04008         }
04009       
04010       }
04011 
04012     
04013 
04014 
04015     else
04016       {
04017       const uschar *pp = eptr;
04018       switch(ctype)
04019         {
04020         case OP_ANY:
04021         if ((ims & PCRE_DOTALL) == 0)
04022           {
04023           for (i = min; i < max; i++)
04024             {
04025             if (eptr >= md->end_subject || *eptr == '\n') break;
04026             eptr++;
04027             }
04028           }
04029         else
04030           {
04031           c = max - min;
04032           if (c > md->end_subject - eptr) c = md->end_subject - eptr;
04033           eptr += c;
04034           }
04035         break;
04036 
04037         case OP_NOT_DIGIT:
04038         for (i = min; i < max; i++)
04039           {
04040           if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
04041             break;
04042           eptr++;
04043           }
04044         break;
04045 
04046         case OP_DIGIT:
04047         for (i = min; i < max; i++)
04048           {
04049           if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
04050             break;
04051           eptr++;
04052           }
04053         break;
04054 
04055         case OP_NOT_WHITESPACE:
04056         for (i = min; i < max; i++)
04057           {
04058           if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
04059             break;
04060           eptr++;
04061           }
04062         break;
04063 
04064         case OP_WHITESPACE:
04065         for (i = min; i < max; i++)
04066           {
04067           if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
04068             break;
04069           eptr++;
04070           }
04071         break;
04072 
04073         case OP_NOT_WORDCHAR:
04074         for (i = min; i < max; i++)
04075           {
04076           if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
04077             break;
04078           eptr++;
04079           }
04080         break;
04081 
04082         case OP_WORDCHAR:
04083         for (i = min; i < max; i++)
04084           {
04085           if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
04086             break;
04087           eptr++;
04088           }
04089         break;
04090         }
04091 
04092       while (eptr >= pp)
04093         if (match(eptr--, ecode, offset_top, md, ims, FALSE, eptrb))
04094           return TRUE;
04095       return FALSE;
04096       }
04097     
04098 
04099     
04100 
04101     default:
04102     DPRINTF(("Unknown opcode %d\n", *ecode));
04103     md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
04104     return FALSE;
04105     }
04106 
04107   
04108 
04109 
04110 
04111   }             
04112 
04113 }
04114 
04115 
04116 
04117 
04118 
04119 
04120 
04121 
04122 
04123 
04124 
04125 
04126 
04127 
04128 
04129 
04130 
04131 
04132 
04133 
04134 
04135 
04136 
04137 
04138 
04139 
04140 
04141 
04142 int
04143 vmdpcre_exec(const pcre *external_re, const pcre_extra *external_extra,
04144   const char *subject, int length, int start_offset, int options, int *offsets,
04145   int offsetcount)
04146 {
04147 int resetcount, ocount;
04148 int first_char = -1;
04149 int ims = 0;
04150 match_data match_block;
04151 const uschar *start_bits = NULL;
04152 const uschar *start_match = (const uschar *)subject + start_offset;
04153 const uschar *end_subject;
04154 const real_pcre *re = (const real_pcre *)external_re;
04155 const real_pcre_extra *extra = (const real_pcre_extra *)external_extra;
04156 BOOL using_temporary_offsets = FALSE;
04157 BOOL anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
04158 BOOL startline = (re->options & PCRE_STARTLINE) != 0;
04159 
04160 if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
04161 
04162 if (re == NULL || subject == NULL ||
04163    (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
04164 if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
04165 
04166 match_block.start_subject = (const uschar *)subject;
04167 match_block.end_subject = match_block.start_subject + length;
04168 end_subject = match_block.end_subject;
04169 
04170 match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
04171 
04172 match_block.notbol = (options & PCRE_NOTBOL) != 0;
04173 match_block.noteol = (options & PCRE_NOTEOL) != 0;
04174 
04175 match_block.errorcode = PCRE_ERROR_NOMATCH;     
04176 
04177 match_block.lcc = re->tables + lcc_offset;
04178 match_block.ctypes = re->tables + ctypes_offset;
04179 
04180 
04181 
04182 
04183 
04184 ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
04185 
04186 
04187 
04188 
04189 
04190 
04191 ocount = offsetcount - (offsetcount % 3);
04192 
04193 if (re->top_backref > 0 && re->top_backref >= ocount/3)
04194   {
04195   ocount = re->top_backref * 3 + 3;
04196   match_block.offset_vector = (int *)(vmdpcre_malloc)(ocount * sizeof(int));
04197   if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
04198   using_temporary_offsets = TRUE;
04199   DPRINTF(("Got memory to hold back references\n"));
04200   }
04201 else match_block.offset_vector = offsets;
04202 
04203 match_block.offset_end = ocount;
04204 match_block.offset_max = (2*ocount)/3;
04205 match_block.offset_overflow = FALSE;
04206 
04207 
04208 
04209 
04210 
04211 resetcount = 2 + re->top_bracket * 2;
04212 if (resetcount > offsetcount) resetcount = ocount;
04213 
04214 
04215 
04216 
04217 
04218 if (match_block.offset_vector != NULL)
04219   {
04220   register int *iptr = match_block.offset_vector + ocount;
04221   register int *iend = iptr - resetcount/2 + 1;
04222   while (--iptr >= iend) *iptr = -1;
04223   }
04224 
04225 
04226 
04227 
04228 
04229 
04230 
04231 if (!anchored)
04232   {
04233   if ((re->options & PCRE_FIRSTSET) != 0)
04234     {
04235     first_char = re->first_char;
04236     if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char];
04237     }
04238   else
04239     if (!startline && extra != NULL &&
04240       (extra->options & PCRE_STUDY_MAPPED) != 0)
04241         start_bits = extra->start_bits;
04242   }
04243 
04244 
04245 
04246 do
04247   {
04248   int rc;
04249   register int *iptr = match_block.offset_vector;
04250   register int *iend = iptr + resetcount;
04251 
04252   
04253 
04254   while (iptr < iend) *iptr++ = -1;
04255 
04256   
04257 
04258   if (first_char >= 0)
04259     {
04260     if ((ims & PCRE_CASELESS) != 0)
04261       while (start_match < end_subject &&
04262              match_block.lcc[*start_match] != first_char)
04263         start_match++;
04264     else
04265       while (start_match < end_subject && *start_match != first_char)
04266         start_match++;
04267     }
04268 
04269   
04270 
04271   else if (startline)
04272     {
04273     if (start_match > match_block.start_subject)
04274       {
04275       while (start_match < end_subject && start_match[-1] != '\n')
04276         start_match++;
04277       }
04278     }
04279 
04280   
04281 
04282   else if (start_bits != NULL)
04283     {
04284     while (start_match < end_subject)
04285       {
04286       register int c = *start_match;
04287       if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
04288       }
04289     }
04290 
04291 #ifdef DEBUG  
04292   printf(">>>> Match against: ");
04293   pchars(start_match, end_subject - start_match, TRUE, &match_block);
04294   printf("\n");
04295 #endif
04296 
04297   
04298 
04299 
04300 
04301 
04302 
04303 
04304   if (!match(start_match, re->code, 2, &match_block, ims, FALSE, start_match))
04305     continue;
04306 
04307   
04308 
04309   if (using_temporary_offsets)
04310     {
04311     if (offsetcount >= 4)
04312       {
04313       memcpy(offsets + 2, match_block.offset_vector + 2,
04314         (offsetcount - 2) * sizeof(int));
04315       DPRINTF(("Copied offsets from temporary memory\n"));
04316       }
04317     if (match_block.end_offset_top > offsetcount)
04318       match_block.offset_overflow = TRUE;
04319 
04320     DPRINTF(("Freeing temporary memory\n"));
04321     (vmdpcre_free)(match_block.offset_vector);
04322     }
04323 
04324   rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
04325 
04326   if (match_block.offset_end < 2) rc = 0; else
04327     {
04328     offsets[0] = start_match - match_block.start_subject;
04329     offsets[1] = match_block.end_match_ptr - match_block.start_subject;
04330     }
04331 
04332   DPRINTF((">>>> returning %d\n", rc));
04333   return rc;
04334   }
04335 
04336 
04337 
04338 while (!anchored &&
04339        match_block.errorcode == PCRE_ERROR_NOMATCH &&
04340        start_match++ < end_subject);
04341 
04342 if (using_temporary_offsets)
04343   {
04344   DPRINTF(("Freeing temporary memory\n"));
04345   (vmdpcre_free)(match_block.offset_vector);
04346   }
04347 
04348 DPRINTF((">>>> returning %d\n", match_block.errorcode));
04349 
04350 return match_block.errorcode;
04351 }
04352 
04353 #ifdef __cplusplus
04354 }
04355 #endif
04356 
04357