/[pcre]/code/trunk/pcre_exec.c
ViewVC logotype

Diff of /code/trunk/pcre_exec.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 403 by ph10, Sat Mar 21 17:33:11 2009 UTC revision 446 by ph10, Tue Sep 15 10:49:50 2009 UTC
# Line 322  typedef struct heapframe { Line 322  typedef struct heapframe {
322    
323    /* Function arguments that may change */    /* Function arguments that may change */
324    
325    const uschar *Xeptr;    USPTR Xeptr;
326    const uschar *Xecode;    const uschar *Xecode;
327    const uschar *Xmstart;    USPTR Xmstart;
328    int Xoffset_top;    int Xoffset_top;
329    long int Xims;    long int Xims;
330    eptrblock *Xeptrb;    eptrblock *Xeptrb;
# Line 333  typedef struct heapframe { Line 333  typedef struct heapframe {
333    
334    /* Function local variables */    /* Function local variables */
335    
336    const uschar *Xcallpat;    USPTR Xcallpat;
337  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
338    const uschar *Xcharptr;    USPTR Xcharptr;
339  #endif  #endif
340    const uschar *Xdata;    USPTR Xdata;
341    const uschar *Xnext;    USPTR Xnext;
342    const uschar *Xpp;    USPTR Xpp;
343    const uschar *Xprev;    USPTR Xprev;
344    const uschar *Xsaved_eptr;    USPTR Xsaved_eptr;
345    
346    recursion_info Xnew_recursive;    recursion_info Xnew_recursive;
347    
# Line 398  typedef struct heapframe { Line 398  typedef struct heapframe {
398    
399  /* This function is called recursively in many circumstances. Whenever it  /* This function is called recursively in many circumstances. Whenever it
400  returns a negative (error) response, the outer incarnation must also return the  returns a negative (error) response, the outer incarnation must also return the
401  same response.  same response. */
402    
403    /* These macros pack up tests that are used for partial matching, and which
404    appears several times in the code. We set the "hit end" flag if the pointer is
405    at the end of the subject and also past the start of the subject (i.e.
406    something has been matched). For hard partial matching, we then return
407    immediately. The second one is used when we already know we are past the end of
408    the subject. */
409    
410    #define CHECK_PARTIAL()\
411      if (md->partial != 0 && eptr >= md->end_subject && eptr > mstart)\
412        {\
413        md->hitend = TRUE;\
414        if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);\
415        }
416    
417    #define SCHECK_PARTIAL()\
418      if (md->partial && eptr > mstart)\
419        {\
420        md->hitend = TRUE;\
421        if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);\
422        }
423    
424  Performance note: It might be tempting to extract commonly used fields from the  
425  md structure (e.g. utf8, end_subject) into individual variables to improve  /* Performance note: It might be tempting to extract commonly used fields from
426    the md structure (e.g. utf8, end_subject) into individual variables to improve
427  performance. Tests using gcc on a SPARC disproved this; in the first case, it  performance. Tests using gcc on a SPARC disproved this; in the first case, it
428  made performance worse.  made performance worse.
429    
# Line 428  Returns:       MATCH_MATCH if matched Line 450  Returns:       MATCH_MATCH if matched
450  */  */
451    
452  static int  static int
453  match(REGISTER USPTR eptr, REGISTER const uschar *ecode, const uschar *mstart,  match(REGISTER USPTR eptr, REGISTER const uschar *ecode, USPTR mstart,
454    int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,    int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
455    int flags, unsigned int rdepth)    int flags, unsigned int rdepth)
456  {  {
# Line 641  for (;;) Line 663  for (;;)
663    {    {
664    minimize = possessive = FALSE;    minimize = possessive = FALSE;
665    op = *ecode;    op = *ecode;
   
   /* For partial matching, remember if we ever hit the end of the subject after  
   matching at least one subject character. */  
   
   if (md->partial &&  
       eptr >= md->end_subject &&  
       eptr > mstart)  
     md->hitend = TRUE;  
666    
667    switch(op)    switch(op)
668      {      {
# Line 794  for (;;) Line 808  for (;;)
808      case OP_COND:      case OP_COND:
809      case OP_SCOND:      case OP_SCOND:
810      codelink= GET(ecode, 1);      codelink= GET(ecode, 1);
811    
812      /* Because of the way auto-callout works during compile, a callout item is      /* Because of the way auto-callout works during compile, a callout item is
813      inserted between OP_COND and an assertion condition. */      inserted between OP_COND and an assertion condition. */
814    
# Line 822  for (;;) Line 836  for (;;)
836        }        }
837    
838      condcode = ecode[LINK_SIZE+1];      condcode = ecode[LINK_SIZE+1];
839    
840      /* Now see what the actual condition is */      /* Now see what the actual condition is */
841    
842      if (condcode == OP_RREF)         /* Recursion test */      if (condcode == OP_RREF)         /* Recursion test */
# Line 910  for (;;) Line 924  for (;;)
924        md->recursive = rec->prevrec;        md->recursive = rec->prevrec;
925        memmove(md->offset_vector, rec->offset_save,        memmove(md->offset_vector, rec->offset_save,
926          rec->saved_max * sizeof(int));          rec->saved_max * sizeof(int));
927          offset_top = rec->offset_top;
928        mstart = rec->save_start;        mstart = rec->save_start;
929        ims = original_ims;        ims = original_ims;
930        ecode = rec->after_call;        ecode = rec->after_call;
931        break;        break;
932        }        }
933    
934      /* Otherwise, if PCRE_NOTEMPTY is set, fail if we have matched an empty      /* Otherwise, if we have matched an empty string, fail if PCRE_NOTEMPTY is
935      string - backtracking will then try other alternatives, if any. */      set, or if PCRE_NOTEMPTY_ATSTART is set and we have matched at the start of
936        the subject. In both cases, backtracking will then try other alternatives,
937        if any. */
938    
939        if (eptr == mstart &&
940            (md->notempty ||
941              (md->notempty_atstart &&
942                mstart == md->start_subject + md->start_offset)))
943          RRETURN(MATCH_NOMATCH);
944    
945        /* Otherwise, we have a match. */
946    
     if (md->notempty && eptr == mstart) RRETURN(MATCH_NOMATCH);  
947      md->end_match_ptr = eptr;           /* Record where we ended */      md->end_match_ptr = eptr;           /* Record where we ended */
948      md->end_offset_top = offset_top;    /* and how many extracts were taken */      md->end_offset_top = offset_top;    /* and how many extracts were taken */
949      md->start_match_ptr = mstart;       /* and the start (\K can modify) */      md->start_match_ptr = mstart;       /* and the start (\K can modify) */
# Line 1010  for (;;) Line 1034  for (;;)
1034        if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);        if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
1035        }        }
1036    
1037      /* Skip to next op code */      /* Save the earliest consulted character, then skip to next op code */
1038    
1039        if (eptr < md->start_used_ptr) md->start_used_ptr = eptr;
1040      ecode += 1 + LINK_SIZE;      ecode += 1 + LINK_SIZE;
1041      break;      break;
1042    
# Line 1091  for (;;) Line 1116  for (;;)
1116        memcpy(new_recursive.offset_save, md->offset_vector,        memcpy(new_recursive.offset_save, md->offset_vector,
1117              new_recursive.saved_max * sizeof(int));              new_recursive.saved_max * sizeof(int));
1118        new_recursive.save_start = mstart;        new_recursive.save_start = mstart;
1119          new_recursive.offset_top = offset_top;
1120        mstart = eptr;        mstart = eptr;
1121    
1122        /* OK, now we can do the recursion. For each top-level alternative we        /* OK, now we can do the recursion. For each top-level alternative we
# Line 1289  for (;;) Line 1315  for (;;)
1315        {        {
1316        number = GET2(prev, 1+LINK_SIZE);        number = GET2(prev, 1+LINK_SIZE);
1317        offset = number << 1;        offset = number << 1;
1318    
1319  #ifdef DEBUG  #ifdef DEBUG
1320        printf("end bracket %d", number);        printf("end bracket %d", number);
1321        printf("\n");        printf("\n");
# Line 1315  for (;;) Line 1341  for (;;)
1341          mstart = rec->save_start;          mstart = rec->save_start;
1342          memcpy(md->offset_vector, rec->offset_save,          memcpy(md->offset_vector, rec->offset_save,
1343            rec->saved_max * sizeof(int));            rec->saved_max * sizeof(int));
1344            offset_top = rec->offset_top;
1345          ecode = rec->after_call;          ecode = rec->after_call;
1346          ims = original_ims;          ims = original_ims;
1347          break;          break;
# Line 1454  for (;;) Line 1481  for (;;)
1481    
1482        /* Find out if the previous and current characters are "word" characters.        /* Find out if the previous and current characters are "word" characters.
1483        It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to        It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to
1484        be "non-word" characters. */        be "non-word" characters. Remember the earliest consulted character for
1485          partial matching. */
1486    
1487  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
1488        if (utf8)        if (utf8)
1489          {          {
1490          if (eptr == md->start_subject) prev_is_word = FALSE; else          if (eptr == md->start_subject) prev_is_word = FALSE; else
1491            {            {
1492            const uschar *lastptr = eptr - 1;            USPTR lastptr = eptr - 1;
1493            while((*lastptr & 0xc0) == 0x80) lastptr--;            while((*lastptr & 0xc0) == 0x80) lastptr--;
1494              if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr;
1495            GETCHAR(c, lastptr);            GETCHAR(c, lastptr);
1496            prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;            prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
1497            }            }
1498          if (eptr >= md->end_subject) cur_is_word = FALSE; else          if (eptr >= md->end_subject)
1499              {
1500              SCHECK_PARTIAL();
1501              cur_is_word = FALSE;
1502              }
1503            else
1504            {            {
1505            GETCHAR(c, eptr);            GETCHAR(c, eptr);
1506            cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;            cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
# Line 1475  for (;;) Line 1509  for (;;)
1509        else        else
1510  #endif  #endif
1511    
1512        /* More streamlined when not in UTF-8 mode */        /* Not in UTF-8 mode */
1513    
1514          {          {
1515          prev_is_word = (eptr != md->start_subject) &&          if (eptr == md->start_subject) prev_is_word = FALSE; else
1516            ((md->ctypes[eptr[-1]] & ctype_word) != 0);            {
1517          cur_is_word = (eptr < md->end_subject) &&            if (eptr <= md->start_used_ptr) md->start_used_ptr = eptr - 1;
1518            ((md->ctypes[*eptr] & ctype_word) != 0);            prev_is_word = ((md->ctypes[eptr[-1]] & ctype_word) != 0);
1519              }
1520            if (eptr >= md->end_subject)
1521              {
1522              SCHECK_PARTIAL();
1523              cur_is_word = FALSE;
1524              }
1525            else cur_is_word = ((md->ctypes[*eptr] & ctype_word) != 0);
1526          }          }
1527    
1528        /* Now see if the situation is what we want */        /* Now see if the situation is what we want */
# Line 1499  for (;;) Line 1540  for (;;)
1540      /* Fall through */      /* Fall through */
1541    
1542      case OP_ALLANY:      case OP_ALLANY:
1543      if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr++ >= md->end_subject)
1544          {
1545          SCHECK_PARTIAL();
1546          RRETURN(MATCH_NOMATCH);
1547          }
1548      if (utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;      if (utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1549      ecode++;      ecode++;
1550      break;      break;
# Line 1508  for (;;) Line 1553  for (;;)
1553      any byte, even newline, independent of the setting of PCRE_DOTALL. */      any byte, even newline, independent of the setting of PCRE_DOTALL. */
1554    
1555      case OP_ANYBYTE:      case OP_ANYBYTE:
1556      if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr++ >= md->end_subject)
1557          {
1558          SCHECK_PARTIAL();
1559          RRETURN(MATCH_NOMATCH);
1560          }
1561      ecode++;      ecode++;
1562      break;      break;
1563    
1564      case OP_NOT_DIGIT:      case OP_NOT_DIGIT:
1565      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1566          {
1567          SCHECK_PARTIAL();
1568          RRETURN(MATCH_NOMATCH);
1569          }
1570      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1571      if (      if (
1572  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
# Line 1526  for (;;) Line 1579  for (;;)
1579      break;      break;
1580    
1581      case OP_DIGIT:      case OP_DIGIT:
1582      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1583          {
1584          SCHECK_PARTIAL();
1585          RRETURN(MATCH_NOMATCH);
1586          }
1587      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1588      if (      if (
1589  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
# Line 1539  for (;;) Line 1596  for (;;)
1596      break;      break;
1597    
1598      case OP_NOT_WHITESPACE:      case OP_NOT_WHITESPACE:
1599      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1600          {
1601          SCHECK_PARTIAL();
1602          RRETURN(MATCH_NOMATCH);
1603          }
1604      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1605      if (      if (
1606  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
# Line 1552  for (;;) Line 1613  for (;;)
1613      break;      break;
1614    
1615      case OP_WHITESPACE:      case OP_WHITESPACE:
1616      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1617          {
1618          SCHECK_PARTIAL();
1619          RRETURN(MATCH_NOMATCH);
1620          }
1621      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1622      if (      if (
1623  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
# Line 1565  for (;;) Line 1630  for (;;)
1630      break;      break;
1631    
1632      case OP_NOT_WORDCHAR:      case OP_NOT_WORDCHAR:
1633      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1634          {
1635          SCHECK_PARTIAL();
1636          RRETURN(MATCH_NOMATCH);
1637          }
1638      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1639      if (      if (
1640  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
# Line 1578  for (;;) Line 1647  for (;;)
1647      break;      break;
1648    
1649      case OP_WORDCHAR:      case OP_WORDCHAR:
1650      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1651          {
1652          SCHECK_PARTIAL();
1653          RRETURN(MATCH_NOMATCH);
1654          }
1655      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1656      if (      if (
1657  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
# Line 1591  for (;;) Line 1664  for (;;)
1664      break;      break;
1665    
1666      case OP_ANYNL:      case OP_ANYNL:
1667      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1668          {
1669          SCHECK_PARTIAL();
1670          RRETURN(MATCH_NOMATCH);
1671          }
1672      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1673      switch(c)      switch(c)
1674        {        {
# Line 1615  for (;;) Line 1692  for (;;)
1692      break;      break;
1693    
1694      case OP_NOT_HSPACE:      case OP_NOT_HSPACE:
1695      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1696          {
1697          SCHECK_PARTIAL();
1698          RRETURN(MATCH_NOMATCH);
1699          }
1700      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1701      switch(c)      switch(c)
1702        {        {
# Line 1645  for (;;) Line 1726  for (;;)
1726      break;      break;
1727    
1728      case OP_HSPACE:      case OP_HSPACE:
1729      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1730          {
1731          SCHECK_PARTIAL();
1732          RRETURN(MATCH_NOMATCH);
1733          }
1734      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1735      switch(c)      switch(c)
1736        {        {
# Line 1675  for (;;) Line 1760  for (;;)
1760      break;      break;
1761    
1762      case OP_NOT_VSPACE:      case OP_NOT_VSPACE:
1763      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1764          {
1765          SCHECK_PARTIAL();
1766          RRETURN(MATCH_NOMATCH);
1767          }
1768      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1769      switch(c)      switch(c)
1770        {        {
# Line 1693  for (;;) Line 1782  for (;;)
1782      break;      break;
1783    
1784      case OP_VSPACE:      case OP_VSPACE:
1785      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1786          {
1787          SCHECK_PARTIAL();
1788          RRETURN(MATCH_NOMATCH);
1789          }
1790      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1791      switch(c)      switch(c)
1792        {        {
# Line 1716  for (;;) Line 1809  for (;;)
1809    
1810      case OP_PROP:      case OP_PROP:
1811      case OP_NOTPROP:      case OP_NOTPROP:
1812      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1813          {
1814          SCHECK_PARTIAL();
1815          RRETURN(MATCH_NOMATCH);
1816          }
1817      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1818        {        {
1819        const ucd_record *prop = GET_UCD(c);        const ucd_record *prop = GET_UCD(c);
# Line 1761  for (;;) Line 1858  for (;;)
1858      is in the binary; otherwise a compile-time error occurs. */      is in the binary; otherwise a compile-time error occurs. */
1859    
1860      case OP_EXTUNI:      case OP_EXTUNI:
1861      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
1862          {
1863          SCHECK_PARTIAL();
1864          RRETURN(MATCH_NOMATCH);
1865          }
1866      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
1867        {        {
1868        int category = UCD_CATEGORY(c);        int category = UCD_CATEGORY(c);
# Line 1841  for (;;) Line 1942  for (;;)
1942          break;          break;
1943    
1944          default:               /* No repeat follows */          default:               /* No repeat follows */
1945          if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH);          if (!match_ref(offset, eptr, length, md, ims))
1946              {
1947              CHECK_PARTIAL();
1948              RRETURN(MATCH_NOMATCH);
1949              }
1950          eptr += length;          eptr += length;
1951          continue;              /* With the main loop */          continue;              /* With the main loop */
1952          }          }
# Line 1857  for (;;) Line 1962  for (;;)
1962    
1963        for (i = 1; i <= min; i++)        for (i = 1; i <= min; i++)
1964          {          {
1965          if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH);          if (!match_ref(offset, eptr, length, md, ims))
1966              {
1967              CHECK_PARTIAL();
1968              RRETURN(MATCH_NOMATCH);
1969              }
1970          eptr += length;          eptr += length;
1971          }          }
1972    
# Line 1874  for (;;) Line 1983  for (;;)
1983            {            {
1984            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14);
1985            if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
1986            if (fi >= max || !match_ref(offset, eptr, length, md, ims))            if (fi >= max) RRETURN(MATCH_NOMATCH);
1987              if (!match_ref(offset, eptr, length, md, ims))
1988                {
1989                CHECK_PARTIAL();
1990              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
1991                }
1992            eptr += length;            eptr += length;
1993            }            }
1994          /* Control never gets here */          /* Control never gets here */
# Line 1902  for (;;) Line 2015  for (;;)
2015        }        }
2016      /* Control never gets here */      /* Control never gets here */
2017    
   
   
2018      /* Match a bit-mapped character class, possibly repeatedly. This op code is      /* Match a bit-mapped character class, possibly repeatedly. This op code is
2019      used when all the characters in the class have values in the range 0-255,      used when all the characters in the class have values in the range 0-255,
2020      and either the matching is caseful, or the characters are in the range      and either the matching is caseful, or the characters are in the range
# Line 1958  for (;;) Line 2069  for (;;)
2069          {          {
2070          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
2071            {            {
2072            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
2073                {
2074                SCHECK_PARTIAL();
2075                RRETURN(MATCH_NOMATCH);
2076                }
2077            GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
2078            if (c > 255)            if (c > 255)
2079              {              {
# Line 1976  for (;;) Line 2091  for (;;)
2091          {          {
2092          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
2093            {            {
2094            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
2095                {
2096                SCHECK_PARTIAL();
2097                RRETURN(MATCH_NOMATCH);
2098                }
2099            c = *eptr++;            c = *eptr++;
2100            if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);            if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
2101            }            }
# Line 2000  for (;;) Line 2119  for (;;)
2119              {              {
2120              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16);
2121              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2122              if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
2123                if (eptr >= md->end_subject)
2124                  {
2125                  SCHECK_PARTIAL();
2126                  RRETURN(MATCH_NOMATCH);
2127                  }
2128              GETCHARINC(c, eptr);              GETCHARINC(c, eptr);
2129              if (c > 255)              if (c > 255)
2130                {                {
# Line 2020  for (;;) Line 2144  for (;;)
2144              {              {
2145              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17);
2146              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2147              if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
2148                if (eptr >= md->end_subject)
2149                  {
2150                  SCHECK_PARTIAL();
2151                  RRETURN(MATCH_NOMATCH);
2152                  }
2153              c = *eptr++;              c = *eptr++;
2154              if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);              if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
2155              }              }
# Line 2129  for (;;) Line 2258  for (;;)
2258    
2259        for (i = 1; i <= min; i++)        for (i = 1; i <= min; i++)
2260          {          {
2261          if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);          if (eptr >= md->end_subject)
2262              {
2263              SCHECK_PARTIAL();
2264              RRETURN(MATCH_NOMATCH);
2265              }
2266          GETCHARINCTEST(c, eptr);          GETCHARINCTEST(c, eptr);
2267          if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);          if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);
2268          }          }
# Line 2148  for (;;) Line 2281  for (;;)
2281            {            {
2282            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20);
2283            if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2284            if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (fi >= max) RRETURN(MATCH_NOMATCH);
2285              if (eptr >= md->end_subject)
2286                {
2287                SCHECK_PARTIAL();
2288                RRETURN(MATCH_NOMATCH);
2289                }
2290            GETCHARINCTEST(c, eptr);            GETCHARINCTEST(c, eptr);
2291            if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);            if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);
2292            }            }
# Line 2191  for (;;) Line 2329  for (;;)
2329        length = 1;        length = 1;
2330        ecode++;        ecode++;
2331        GETCHARLEN(fc, ecode, length);        GETCHARLEN(fc, ecode, length);
2332        if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);        if (length > md->end_subject - eptr)
2333            {
2334            CHECK_PARTIAL();             /* Not SCHECK_PARTIAL() */
2335            RRETURN(MATCH_NOMATCH);
2336            }
2337        while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH);        while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH);
2338        }        }
2339      else      else
# Line 2199  for (;;) Line 2341  for (;;)
2341    
2342      /* Non-UTF-8 mode */      /* Non-UTF-8 mode */
2343        {        {
2344        if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH);        if (md->end_subject - eptr < 1)
2345            {
2346            SCHECK_PARTIAL();            /* This one can use SCHECK_PARTIAL() */
2347            RRETURN(MATCH_NOMATCH);
2348            }
2349        if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH);        if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH);
2350        ecode += 2;        ecode += 2;
2351        }        }
# Line 2215  for (;;) Line 2361  for (;;)
2361        ecode++;        ecode++;
2362        GETCHARLEN(fc, ecode, length);        GETCHARLEN(fc, ecode, length);
2363    
2364        if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);        if (length > md->end_subject - eptr)
2365            {
2366            CHECK_PARTIAL();             /* Not SCHECK_PARTIAL() */
2367            RRETURN(MATCH_NOMATCH);
2368            }
2369    
2370        /* If the pattern character's value is < 128, we have only one byte, and        /* If the pattern character's value is < 128, we have only one byte, and
2371        can use the fast lookup table. */        can use the fast lookup table. */
# Line 2250  for (;;) Line 2400  for (;;)
2400    
2401      /* Non-UTF-8 mode */      /* Non-UTF-8 mode */
2402        {        {
2403        if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH);        if (md->end_subject - eptr < 1)
2404            {
2405            SCHECK_PARTIAL();            /* This one can use SCHECK_PARTIAL() */
2406            RRETURN(MATCH_NOMATCH);
2407            }
2408        if (md->lcc[ecode[1]] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);        if (md->lcc[ecode[1]] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
2409        ecode += 2;        ecode += 2;
2410        }        }
# Line 2304  for (;;) Line 2458  for (;;)
2458      case OP_MINQUERY:      case OP_MINQUERY:
2459      c = *ecode++ - OP_STAR;      c = *ecode++ - OP_STAR;
2460      minimize = (c & 1) != 0;      minimize = (c & 1) != 0;
2461    
2462      min = rep_min[c];                 /* Pick up values from tables; */      min = rep_min[c];                 /* Pick up values from tables; */
2463      max = rep_max[c];                 /* zero for max => infinity */      max = rep_max[c];                 /* zero for max => infinity */
2464      if (max == 0) max = INT_MAX;      if (max == 0) max = INT_MAX;
2465    
2466      /* Common code for all repeated single-character matches. We can give      /* Common code for all repeated single-character matches. */
     up quickly if there are fewer than the minimum number of characters left in  
     the subject. */  
2467    
2468      REPEATCHAR:      REPEATCHAR:
2469  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
# Line 2319  for (;;) Line 2472  for (;;)
2472        length = 1;        length = 1;
2473        charptr = ecode;        charptr = ecode;
2474        GETCHARLEN(fc, ecode, length);        GETCHARLEN(fc, ecode, length);
       if (min * length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);  
2475        ecode += length;        ecode += length;
2476    
2477        /* Handle multibyte character matching specially here. There is        /* Handle multibyte character matching specially here. There is
# Line 2337  for (;;) Line 2489  for (;;)
2489    
2490          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
2491            {            {
2492            if (memcmp(eptr, charptr, length) == 0) eptr += length;            if (eptr <= md->end_subject - length &&
2493                memcmp(eptr, charptr, length) == 0) eptr += length;
2494  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2495            /* Need braces because of following else */            else if (oclength > 0 &&
2496            else if (oclength == 0) { RRETURN(MATCH_NOMATCH); }                     eptr <= md->end_subject - oclength &&
2497                       memcmp(eptr, occhars, oclength) == 0) eptr += oclength;
2498    #endif  /* SUPPORT_UCP */
2499            else            else
2500              {              {
2501              if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH);              CHECK_PARTIAL();
2502              eptr += oclength;              RRETURN(MATCH_NOMATCH);
2503              }              }
 #else   /* without SUPPORT_UCP */  
           else { RRETURN(MATCH_NOMATCH); }  
 #endif  /* SUPPORT_UCP */  
2504            }            }
2505    
2506          if (min == max) continue;          if (min == max) continue;
# Line 2359  for (;;) Line 2511  for (;;)
2511              {              {
2512              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22);
2513              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2514              if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
2515              if (memcmp(eptr, charptr, length) == 0) eptr += length;              if (eptr <= md->end_subject - length &&
2516                  memcmp(eptr, charptr, length) == 0) eptr += length;
2517  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2518              /* Need braces because of following else */              else if (oclength > 0 &&
2519              else if (oclength == 0) { RRETURN(MATCH_NOMATCH); }                       eptr <= md->end_subject - oclength &&
2520                         memcmp(eptr, occhars, oclength) == 0) eptr += oclength;
2521    #endif  /* SUPPORT_UCP */
2522              else              else
2523                {                {
2524                if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH);                CHECK_PARTIAL();
2525                eptr += oclength;                RRETURN(MATCH_NOMATCH);
2526                }                }
 #else   /* without SUPPORT_UCP */  
             else { RRETURN (MATCH_NOMATCH); }  
 #endif  /* SUPPORT_UCP */  
2527              }              }
2528            /* Control never gets here */            /* Control never gets here */
2529            }            }
# Line 2381  for (;;) Line 2533  for (;;)
2533            pp = eptr;            pp = eptr;
2534            for (i = min; i < max; i++)            for (i = min; i < max; i++)
2535              {              {
2536              if (eptr > md->end_subject - length) break;              if (eptr <= md->end_subject - length &&
2537              if (memcmp(eptr, charptr, length) == 0) eptr += length;                  memcmp(eptr, charptr, length) == 0) eptr += length;
2538  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2539              else if (oclength == 0) break;              else if (oclength > 0 &&
2540              else                       eptr <= md->end_subject - oclength &&
2541                {                       memcmp(eptr, occhars, oclength) == 0) eptr += oclength;
               if (memcmp(eptr, occhars, oclength) != 0) break;  
               eptr += oclength;  
               }  
 #else   /* without SUPPORT_UCP */  
             else break;  
2542  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2543                else break;
2544              }              }
2545    
2546            if (possessive) continue;            if (possessive) continue;
2547    
2548            for(;;)            for(;;)
2549             {              {
2550             RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23);
2551             if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2552             if (eptr == pp) RRETURN(MATCH_NOMATCH);              if (eptr == pp) { RRETURN(MATCH_NOMATCH); }
2553  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
2554             eptr--;              eptr--;
2555             BACKCHAR(eptr);              BACKCHAR(eptr);
2556  #else   /* without SUPPORT_UCP */  #else   /* without SUPPORT_UCP */
2557             eptr -= length;              eptr -= length;
2558  #endif  /* SUPPORT_UCP */  #endif  /* SUPPORT_UCP */
2559             }              }
2560            }            }
2561          /* Control never gets here */          /* Control never gets here */
2562          }          }
# Line 2420  for (;;) Line 2569  for (;;)
2569  #endif  /* SUPPORT_UTF8 */  #endif  /* SUPPORT_UTF8 */
2570    
2571      /* When not in UTF-8 mode, load a single-byte character. */      /* When not in UTF-8 mode, load a single-byte character. */
2572        {  
2573        if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);      fc = *ecode++;
       fc = *ecode++;  
       }  
2574    
2575      /* The value of fc at this point is always less than 256, though we may or      /* The value of fc at this point is always less than 256, though we may or
2576      may not be in UTF-8 mode. The code is duplicated for the caseless and      may not be in UTF-8 mode. The code is duplicated for the caseless and
# Line 2441  for (;;) Line 2588  for (;;)
2588        {        {
2589        fc = md->lcc[fc];        fc = md->lcc[fc];
2590        for (i = 1; i <= min; i++)        for (i = 1; i <= min; i++)
2591            {
2592            if (eptr >= md->end_subject)
2593              {
2594              SCHECK_PARTIAL();
2595              RRETURN(MATCH_NOMATCH);
2596              }
2597          if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);          if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
2598            }
2599        if (min == max) continue;        if (min == max) continue;
2600        if (minimize)        if (minimize)
2601          {          {
# Line 2449  for (;;) Line 2603  for (;;)
2603            {            {
2604            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24);
2605            if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2606            if (fi >= max || eptr >= md->end_subject ||            if (fi >= max) RRETURN(MATCH_NOMATCH);
2607                fc != md->lcc[*eptr++])            if (eptr >= md->end_subject)
2608                {
2609                SCHECK_PARTIAL();
2610              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
2611                }
2612              if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
2613            }            }
2614          /* Control never gets here */          /* Control never gets here */
2615          }          }
# Line 2463  for (;;) Line 2621  for (;;)
2621            if (eptr >= md->end_subject || fc != md->lcc[*eptr]) break;            if (eptr >= md->end_subject || fc != md->lcc[*eptr]) break;
2622            eptr++;            eptr++;
2623            }            }
2624    
2625          if (possessive) continue;          if (possessive) continue;
2626    
2627          while (eptr >= pp)          while (eptr >= pp)
2628            {            {
2629            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25);
# Line 2479  for (;;) Line 2639  for (;;)
2639    
2640      else      else
2641        {        {
2642        for (i = 1; i <= min; i++) if (fc != *eptr++) RRETURN(MATCH_NOMATCH);        for (i = 1; i <= min; i++)
2643            {
2644            if (eptr >= md->end_subject)
2645              {
2646              SCHECK_PARTIAL();
2647              RRETURN(MATCH_NOMATCH);
2648              }
2649            if (fc != *eptr++) RRETURN(MATCH_NOMATCH);
2650            }
2651    
2652        if (min == max) continue;        if (min == max) continue;
2653    
2654        if (minimize)        if (minimize)
2655          {          {
2656          for (fi = min;; fi++)          for (fi = min;; fi++)
2657            {            {
2658            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26);
2659            if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2660            if (fi >= max || eptr >= md->end_subject || fc != *eptr++)            if (fi >= max) RRETURN(MATCH_NOMATCH);
2661              if (eptr >= md->end_subject)
2662                {
2663                SCHECK_PARTIAL();
2664              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
2665                }
2666              if (fc != *eptr++) RRETURN(MATCH_NOMATCH);
2667            }            }
2668          /* Control never gets here */          /* Control never gets here */
2669          }          }
# Line 2501  for (;;) Line 2676  for (;;)
2676            eptr++;            eptr++;
2677            }            }
2678          if (possessive) continue;          if (possessive) continue;
2679    
2680          while (eptr >= pp)          while (eptr >= pp)
2681            {            {
2682            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM27);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM27);
# Line 2516  for (;;) Line 2692  for (;;)
2692      checking can be multibyte. */      checking can be multibyte. */
2693    
2694      case OP_NOT:      case OP_NOT:
2695      if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);      if (eptr >= md->end_subject)
2696          {
2697          SCHECK_PARTIAL();
2698          RRETURN(MATCH_NOMATCH);
2699          }
2700      ecode++;      ecode++;
2701      GETCHARINCTEST(c, eptr);      GETCHARINCTEST(c, eptr);
2702      if ((ims & PCRE_CASELESS) != 0)      if ((ims & PCRE_CASELESS) != 0)
# Line 2593  for (;;) Line 2773  for (;;)
2773      max = rep_max[c];                 /* zero for max => infinity */      max = rep_max[c];                 /* zero for max => infinity */
2774      if (max == 0) max = INT_MAX;      if (max == 0) max = INT_MAX;
2775    
2776      /* Common code for all repeated single-byte matches. We can give up quickly      /* Common code for all repeated single-byte matches. */
     if there are fewer than the minimum number of bytes left in the  
     subject. */  
2777    
2778      REPEATNOTCHAR:      REPEATNOTCHAR:
     if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);  
2779      fc = *ecode++;      fc = *ecode++;
2780    
2781      /* The code is duplicated for the caseless and caseful cases, for speed,      /* The code is duplicated for the caseless and caseful cases, for speed,
# Line 2623  for (;;) Line 2800  for (;;)
2800          register unsigned int d;          register unsigned int d;
2801          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
2802            {            {
2803              if (eptr >= md->end_subject)
2804                {
2805                SCHECK_PARTIAL();
2806                RRETURN(MATCH_NOMATCH);
2807                }
2808            GETCHARINC(d, eptr);            GETCHARINC(d, eptr);
2809            if (d < 256) d = md->lcc[d];            if (d < 256) d = md->lcc[d];
2810            if (fc == d) RRETURN(MATCH_NOMATCH);            if (fc == d) RRETURN(MATCH_NOMATCH);
# Line 2634  for (;;) Line 2816  for (;;)
2816        /* Not UTF-8 mode */        /* Not UTF-8 mode */
2817          {          {
2818          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
2819              {
2820              if (eptr >= md->end_subject)
2821                {
2822                SCHECK_PARTIAL();
2823                RRETURN(MATCH_NOMATCH);
2824                }
2825            if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);            if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
2826              }
2827          }          }
2828    
2829        if (min == max) continue;        if (min == max) continue;
# Line 2650  for (;;) Line 2839  for (;;)
2839              {              {
2840              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28);
2841              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2842              if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
2843                if (eptr >= md->end_subject)
2844                  {
2845                  SCHECK_PARTIAL();
2846                  RRETURN(MATCH_NOMATCH);
2847                  }
2848              GETCHARINC(d, eptr);              GETCHARINC(d, eptr);
2849              if (d < 256) d = md->lcc[d];              if (d < 256) d = md->lcc[d];
2850              if (fc == d) RRETURN(MATCH_NOMATCH);              if (fc == d) RRETURN(MATCH_NOMATCH);
   
2851              }              }
2852            }            }
2853          else          else
# Line 2665  for (;;) Line 2858  for (;;)
2858              {              {
2859              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29);
2860              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2861              if (fi >= max || eptr >= md->end_subject || fc == md->lcc[*eptr++])              if (fi >= max) RRETURN(MATCH_NOMATCH);
2862                if (eptr >= md->end_subject)
2863                  {
2864                  SCHECK_PARTIAL();
2865                RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
2866                  }
2867                if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
2868              }              }
2869            }            }
2870          /* Control never gets here */          /* Control never gets here */
# Line 2735  for (;;) Line 2933  for (;;)
2933          register unsigned int d;          register unsigned int d;
2934          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
2935            {            {
2936              if (eptr >= md->end_subject)
2937                {
2938                SCHECK_PARTIAL();
2939                RRETURN(MATCH_NOMATCH);
2940                }
2941            GETCHARINC(d, eptr);            GETCHARINC(d, eptr);
2942            if (fc == d) RRETURN(MATCH_NOMATCH);            if (fc == d) RRETURN(MATCH_NOMATCH);
2943            }            }
# Line 2744  for (;;) Line 2947  for (;;)
2947        /* Not UTF-8 mode */        /* Not UTF-8 mode */
2948          {          {
2949          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
2950              {
2951              if (eptr >= md->end_subject)
2952                {
2953                SCHECK_PARTIAL();
2954                RRETURN(MATCH_NOMATCH);
2955                }
2956            if (fc == *eptr++) RRETURN(MATCH_NOMATCH);            if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
2957              }
2958          }          }
2959    
2960        if (min == max) continue;        if (min == max) continue;
# Line 2760  for (;;) Line 2970  for (;;)
2970              {              {
2971              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32);
2972              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2973              if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
2974                if (eptr >= md->end_subject)
2975                  {
2976                  SCHECK_PARTIAL();
2977                  RRETURN(MATCH_NOMATCH);
2978                  }
2979              GETCHARINC(d, eptr);              GETCHARINC(d, eptr);
2980              if (fc == d) RRETURN(MATCH_NOMATCH);              if (fc == d) RRETURN(MATCH_NOMATCH);
2981              }              }
# Line 2773  for (;;) Line 2988  for (;;)
2988              {              {
2989              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33);
2990              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
2991              if (fi >= max || eptr >= md->end_subject || fc == *eptr++)              if (fi >= max) RRETURN(MATCH_NOMATCH);
2992                if (eptr >= md->end_subject)
2993                  {
2994                  SCHECK_PARTIAL();
2995                RRETURN(MATCH_NOMATCH);                RRETURN(MATCH_NOMATCH);
2996                  }
2997                if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
2998              }              }
2999            }            }
3000          /* Control never gets here */          /* Control never gets here */
# Line 2908  for (;;) Line 3128  for (;;)
3128    
3129      /* First, ensure the minimum number of matches are present. Use inline      /* First, ensure the minimum number of matches are present. Use inline
3130      code for maximizing the speed, and do the type test once at the start      code for maximizing the speed, and do the type test once at the start
3131      (i.e. keep it out of the loop). Also we can test that there are at least      (i.e. keep it out of the loop). Separate the UTF-8 code completely as that
     the minimum number of bytes before we start. This isn't as effective in  
     UTF-8 mode, but it does no harm. Separate the UTF-8 code completely as that  
3132      is tidier. Also separate the UCP code, which can be the same for both UTF-8      is tidier. Also separate the UCP code, which can be the same for both UTF-8
3133      and single-bytes. */      and single-bytes. */
3134    
     if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);  
3135      if (min > 0)      if (min > 0)
3136        {        {
3137  #ifdef SUPPORT_UCP  #ifdef SUPPORT_UCP
# Line 2926  for (;;) Line 3143  for (;;)
3143            if (prop_fail_result) RRETURN(MATCH_NOMATCH);            if (prop_fail_result) RRETURN(MATCH_NOMATCH);
3144            for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
3145              {              {
3146              if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
3147                  {
3148                  SCHECK_PARTIAL();
3149                  RRETURN(MATCH_NOMATCH);
3150                  }
3151              GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
3152              }              }
3153            break;            break;
# Line 2934  for (;;) Line 3155  for (;;)
3155            case PT_LAMP:            case PT_LAMP:
3156            for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
3157              {              {
3158              if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
3159                  {
3160                  SCHECK_PARTIAL();
3161                  RRETURN(MATCH_NOMATCH);
3162                  }
3163              GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
3164              prop_chartype = UCD_CHARTYPE(c);              prop_chartype = UCD_CHARTYPE(c);
3165              if ((prop_chartype == ucp_Lu ||              if ((prop_chartype == ucp_Lu ||
# Line 2947  for (;;) Line 3172  for (;;)
3172            case PT_GC:            case PT_GC:
3173            for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
3174              {              {
3175              if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
3176                  {
3177                  SCHECK_PARTIAL();
3178                  RRETURN(MATCH_NOMATCH);
3179                  }
3180              GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
3181              prop_category = UCD_CATEGORY(c);              prop_category = UCD_CATEGORY(c);
3182              if ((prop_category == prop_value) == prop_fail_result)              if ((prop_category == prop_value) == prop_fail_result)
# Line 2958  for (;;) Line 3187  for (;;)
3187            case PT_PC:            case PT_PC:
3188            for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
3189              {              {
3190              if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
3191                  {
3192                  SCHECK_PARTIAL();
3193                  RRETURN(MATCH_NOMATCH);
3194                  }
3195              GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
3196              prop_chartype = UCD_CHARTYPE(c);              prop_chartype = UCD_CHARTYPE(c);
3197              if ((prop_chartype == prop_value) == prop_fail_result)              if ((prop_chartype == prop_value) == prop_fail_result)
# Line 2969  for (;;) Line 3202  for (;;)
3202            case PT_SC:            case PT_SC:
3203            for (i = 1; i <= min; i++)            for (i = 1; i <= min; i++)
3204              {              {
3205              if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (eptr >= md->end_subject)
3206                  {
3207                  SCHECK_PARTIAL();
3208                  RRETURN(MATCH_NOMATCH);
3209                  }
3210              GETCHARINCTEST(c, eptr);              GETCHARINCTEST(c, eptr);
3211              prop_script = UCD_SCRIPT(c);              prop_script = UCD_SCRIPT(c);
3212              if ((prop_script == prop_value) == prop_fail_result)              if ((prop_script == prop_value) == prop_fail_result)
# Line 2989  for (;;) Line 3226  for (;;)
3226          {          {
3227          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3228            {            {
3229              if (eptr >= md->end_subject)
3230                {
3231                SCHECK_PARTIAL();
3232                RRETURN(MATCH_NOMATCH);
3233                }
3234            GETCHARINCTEST(c, eptr);            GETCHARINCTEST(c, eptr);
3235            prop_category = UCD_CATEGORY(c);            prop_category = UCD_CATEGORY(c);
3236            if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);            if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);
3237            while (eptr < md->end_subject)            while (eptr < md->end_subject)
3238              {              {
3239              int len = 1;              int len = 1;
3240              if (!utf8) c = *eptr; else              if (!utf8) c = *eptr;
3241                {                else { GETCHARLEN(c, eptr, len); }
               GETCHARLEN(c, eptr, len);  
               }  
3242              prop_category = UCD_CATEGORY(c);              prop_category = UCD_CATEGORY(c);
3243              if (prop_category != ucp_M) break;              if (prop_category != ucp_M) break;
3244              eptr += len;              eptr += len;
# Line 3017  for (;;) Line 3257  for (;;)
3257          case OP_ANY:          case OP_ANY:
3258          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3259            {            {
3260            if (eptr >= md->end_subject || IS_NEWLINE(eptr))            if (eptr >= md->end_subject)
3261                {
3262                SCHECK_PARTIAL();
3263              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
3264                }
3265              if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
3266            eptr++;            eptr++;
3267            while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;            while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
3268            }            }
# Line 3027  for (;;) Line 3271  for (;;)
3271          case OP_ALLANY:          case OP_ALLANY:
3272          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3273            {            {
3274            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3275                {
3276                SCHECK_PARTIAL();
3277                RRETURN(MATCH_NOMATCH);
3278                }
3279            eptr++;            eptr++;
3280            while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;            while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
3281            }            }
3282          break;          break;
3283    
3284          case OP_ANYBYTE:          case OP_ANYBYTE:
3285            if (eptr > md->end_subject - min) RRETURN(MATCH_NOMATCH);
3286          eptr += min;          eptr += min;
3287          break;          break;
3288    
3289          case OP_ANYNL:          case OP_ANYNL:
3290          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3291            {            {
3292            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3293                {
3294                SCHECK_PARTIAL();
3295                RRETURN(MATCH_NOMATCH);
3296                }
3297            GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
3298            switch(c)            switch(c)
3299              {              {
# Line 3066  for (;;) Line 3319  for (;;)
3319          case OP_NOT_HSPACE:          case OP_NOT_HSPACE:
3320          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3321            {            {
3322            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3323                {
3324                SCHECK_PARTIAL();
3325                RRETURN(MATCH_NOMATCH);
3326                }
3327            GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
3328            switch(c)            switch(c)
3329              {              {
# Line 3098  for (;;) Line 3355  for (;;)
3355          case OP_HSPACE:          case OP_HSPACE:
3356          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3357            {            {
3358            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3359                {
3360                SCHECK_PARTIAL();
3361                RRETURN(MATCH_NOMATCH);
3362                }
3363            GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
3364            switch(c)            switch(c)
3365              {              {
# Line 3130  for (;;) Line 3391  for (;;)
3391          case OP_NOT_VSPACE:          case OP_NOT_VSPACE:
3392          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3393            {            {
3394            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3395                {
3396                SCHECK_PARTIAL();
3397                RRETURN(MATCH_NOMATCH);
3398                }
3399            GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
3400            switch(c)            switch(c)
3401              {              {
# Line 3150  for (;;) Line 3415  for (;;)
3415          case OP_VSPACE:          case OP_VSPACE:
3416          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3417            {            {
3418            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3419                {
3420                SCHECK_PARTIAL();
3421                RRETURN(MATCH_NOMATCH);
3422                }
3423            GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
3424            switch(c)            switch(c)
3425              {              {
# Line 3170  for (;;) Line 3439  for (;;)
3439          case OP_NOT_DIGIT:          case OP_NOT_DIGIT:
3440          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3441            {            {
3442            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3443                {
3444                SCHECK_PARTIAL();
3445                RRETURN(MATCH_NOMATCH);
3446                }
3447            GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
3448            if (c < 128 && (md->ctypes[c] & ctype_digit) != 0)            if (c < 128 && (md->ctypes[c] & ctype_digit) != 0)
3449              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
# Line 3180  for (;;) Line 3453  for (;;)
3453          case OP_DIGIT:          case OP_DIGIT:
3454          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3455            {            {
3456            if (eptr >= md->end_subject ||            if (eptr >= md->end_subject)
3457               *eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0)              {
3458                SCHECK_PARTIAL();
3459                RRETURN(MATCH_NOMATCH);
3460                }
3461              if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0)
3462              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
3463            /* No need to skip more bytes - we know it's a 1-byte character */            /* No need to skip more bytes - we know it's a 1-byte character */
3464            }            }
# Line 3190  for (;;) Line 3467  for (;;)
3467          case OP_NOT_WHITESPACE:          case OP_NOT_WHITESPACE:
3468          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3469            {            {
3470            if (eptr >= md->end_subject ||            if (eptr >= md->end_subject)
3471               (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0))              {
3472                SCHECK_PARTIAL();
3473                RRETURN(MATCH_NOMATCH);
3474                }
3475              if (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0)
3476              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
3477            while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80);            while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80);
3478            }            }
# Line 3200  for (;;) Line 3481  for (;;)
3481          case OP_WHITESPACE:          case OP_WHITESPACE:
3482          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3483            {            {
3484            if (eptr >= md->end_subject ||            if (eptr >= md->end_subject)
3485               *eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0)              {
3486                SCHECK_PARTIAL();
3487                RRETURN(MATCH_NOMATCH);
3488                }
3489              if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0)
3490              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
3491            /* No need to skip more bytes - we know it's a 1-byte character */            /* No need to skip more bytes - we know it's a 1-byte character */
3492            }            }
# Line 3220  for (;;) Line 3505  for (;;)
3505          case OP_WORDCHAR:          case OP_WORDCHAR:
3506          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3507            {            {
3508            if (eptr >= md->end_subject ||            if (eptr >= md->end_subject)
3509               *eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0)              {
3510                SCHECK_PARTIAL();
3511                RRETURN(MATCH_NOMATCH);
3512                }
3513              if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0)
3514              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
3515            /* No need to skip more bytes - we know it's a 1-byte character */            /* No need to skip more bytes - we know it's a 1-byte character */
3516            }            }
# Line 3235  for (;;) Line 3524  for (;;)
3524  #endif     /* SUPPORT_UTF8 */  #endif     /* SUPPORT_UTF8 */
3525    
3526        /* Code for the non-UTF-8 case for minimum matching of operators other        /* Code for the non-UTF-8 case for minimum matching of operators other
3527        than OP_PROP and OP_NOTPROP. We can assume that there are the minimum        than OP_PROP and OP_NOTPROP. */
       number of bytes present, as this was tested above. */  
3528    
3529        switch(ctype)        switch(ctype)
3530          {          {
3531          case OP_ANY:          case OP_ANY:
3532          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3533            {            {
3534              if (eptr >= md->end_subject)
3535                {
3536                SCHECK_PARTIAL();
3537                RRETURN(MATCH_NOMATCH);
3538                }
3539            if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);            if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
3540            eptr++;            eptr++;
3541            }            }
3542          break;          break;
3543    
3544          case OP_ALLANY:          case OP_ALLANY:
3545            if (eptr > md->end_subject - min)
3546              {
3547              SCHECK_PARTIAL();
3548              RRETURN(MATCH_NOMATCH);
3549              }
3550          eptr += min;          eptr += min;
3551          break;          break;
3552    
3553          case OP_ANYBYTE:          case OP_ANYBYTE:
3554            if (eptr > md->end_subject - min)
3555              {
3556              SCHECK_PARTIAL();
3557              RRETURN(MATCH_NOMATCH);
3558              }
3559          eptr += min;          eptr += min;
3560          break;          break;
3561    
         /* Because of the CRLF case, we can't assume the minimum number of  
         bytes are present in this case. */  
   
3562          case OP_ANYNL:          case OP_ANYNL:
3563          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3564            {            {
3565            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3566                {
3567                SCHECK_PARTIAL();
3568                RRETURN(MATCH_NOMATCH);
3569                }
3570            switch(*eptr++)            switch(*eptr++)
3571              {              {
3572              default: RRETURN(MATCH_NOMATCH);              default: RRETURN(MATCH_NOMATCH);
# Line 3284  for (;;) Line 3588  for (;;)
3588          case OP_NOT_HSPACE:          case OP_NOT_HSPACE:
3589          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3590            {            {
3591            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3592                {
3593                SCHECK_PARTIAL();
3594                RRETURN(MATCH_NOMATCH);
3595                }
3596            switch(*eptr++)            switch(*eptr++)
3597              {              {
3598              default: break;              default: break;
# Line 3299  for (;;) Line 3607  for (;;)
3607          case OP_HSPACE:          case OP_HSPACE:
3608          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3609            {            {
3610            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3611                {
3612                SCHECK_PARTIAL();
3613                RRETURN(MATCH_NOMATCH);
3614                }
3615            switch(*eptr++)            switch(*eptr++)
3616              {              {
3617              default: RRETURN(MATCH_NOMATCH);              default: RRETURN(MATCH_NOMATCH);
# Line 3314  for (;;) Line 3626  for (;;)
3626          case OP_NOT_VSPACE:          case OP_NOT_VSPACE:
3627          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3628            {            {
3629            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3630                {
3631                SCHECK_PARTIAL();
3632                RRETURN(MATCH_NOMATCH);
3633                }
3634            switch(*eptr++)            switch(*eptr++)
3635              {              {
3636              default: break;              default: break;
# Line 3331  for (;;) Line 3647  for (;;)
3647          case OP_VSPACE:          case OP_VSPACE:
3648          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3649            {            {
3650            if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (eptr >= md->end_subject)
3651                {
3652                SCHECK_PARTIAL();
3653                RRETURN(MATCH_NOMATCH);
3654                }
3655            switch(*eptr++)            switch(*eptr++)
3656              {              {
3657              default: RRETURN(MATCH_NOMATCH);              default: RRETURN(MATCH_NOMATCH);
# Line 3347  for (;;) Line 3667  for (;;)
3667    
3668          case OP_NOT_DIGIT:          case OP_NOT_DIGIT:
3669          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3670              {
3671              if (eptr >= md->end_subject)
3672                {
3673                SCHECK_PARTIAL();
3674                RRETURN(MATCH_NOMATCH);
3675                }
3676            if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);            if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
3677              }
3678          break;          break;
3679    
3680          case OP_DIGIT:          case OP_DIGIT:
3681          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3682              {
3683              if (eptr >= md->end_subject)
3684                {
3685                SCHECK_PARTIAL();
3686                RRETURN(MATCH_NOMATCH);
3687                }
3688            if ((md->ctypes[*eptr++] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);            if ((md->ctypes[*eptr++] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);
3689              }
3690          break;          break;
3691    
3692          case OP_NOT_WHITESPACE:          case OP_NOT_WHITESPACE:
3693          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3694              {
3695              if (eptr >= md->end_subject)
3696                {
3697                SCHECK_PARTIAL();
3698                RRETURN(MATCH_NOMATCH);
3699                }
3700            if ((md->ctypes[*eptr++] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);            if ((md->ctypes[*eptr++] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);
3701              }
3702          break;          break;
3703    
3704          case OP_WHITESPACE:          case OP_WHITESPACE:
3705          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3706              {
3707              if (eptr >= md->end_subject)
3708                {
3709                SCHECK_PARTIAL();
3710                RRETURN(MATCH_NOMATCH);
3711                }
3712            if ((md->ctypes[*eptr++] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);            if ((md->ctypes[*eptr++] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);
3713              }
3714          break;          break;
3715    
3716          case OP_NOT_WORDCHAR:          case OP_NOT_WORDCHAR:
3717          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3718              {
3719              if (eptr >= md->end_subject)
3720                {
3721                SCHECK_PARTIAL();
3722                RRETURN(MATCH_NOMATCH);
3723                }
3724            if ((md->ctypes[*eptr++] & ctype_word) != 0)            if ((md->ctypes[*eptr++] & ctype_word) != 0)
3725              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
3726              }
3727          break;          break;
3728    
3729          case OP_WORDCHAR:          case OP_WORDCHAR:
3730          for (i = 1; i <= min; i++)          for (i = 1; i <= min; i++)
3731              {
3732              if (eptr >= md->end_subject)
3733                {
3734                SCHECK_PARTIAL();
3735                RRETURN(MATCH_NOMATCH);
3736                }
3737            if ((md->ctypes[*eptr++] & ctype_word) == 0)            if ((md->ctypes[*eptr++] & ctype_word) == 0)
3738              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
3739              }
3740          break;          break;
3741    
3742          default:          default:
# Line 3402  for (;;) Line 3764  for (;;)
3764              {              {
3765              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36);
3766              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
3767              if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
3768                if (eptr >= md->end_subject)
3769                  {
3770                  SCHECK_PARTIAL();
3771                  RRETURN(MATCH_NOMATCH);
3772                  }
3773              GETCHARINC(c, eptr);              GETCHARINC(c, eptr);
3774              if (prop_fail_result) RRETURN(MATCH_NOMATCH);              if (prop_fail_result) RRETURN(MATCH_NOMATCH);
3775              }              }
# Line 3413  for (;;) Line 3780  for (;;)
3780              {              {
3781              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37);
3782              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
3783              if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
3784                if (eptr >= md->end_subject)
3785                  {
3786                  SCHECK_PARTIAL();
3787                  RRETURN(MATCH_NOMATCH);
3788                  }
3789              GETCHARINC(c, eptr);              GETCHARINC(c, eptr);
3790              prop_chartype = UCD_CHARTYPE(c);              prop_chartype = UCD_CHARTYPE(c);
3791              if ((prop_chartype == ucp_Lu ||              if ((prop_chartype == ucp_Lu ||
# Line 3428  for (;;) Line 3800  for (;;)
3800              {              {
3801              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38);
3802              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
3803              if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
3804                if (eptr >= md->end_subject)
3805                  {
3806                  SCHECK_PARTIAL();
3807                  RRETURN(MATCH_NOMATCH);
3808                  }
3809              GETCHARINC(c, eptr);              GETCHARINC(c, eptr);
3810              prop_category = UCD_CATEGORY(c);              prop_category = UCD_CATEGORY(c);
3811              if ((prop_category == prop_value) == prop_fail_result)              if ((prop_category == prop_value) == prop_fail_result)
# Line 3441  for (;;) Line 3818  for (;;)
3818              {              {
3819              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39);
3820              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
3821              if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
3822                if (eptr >= md->end_subject)
3823                  {
3824                  SCHECK_PARTIAL();
3825                  RRETURN(MATCH_NOMATCH);
3826                  }
3827              GETCHARINC(c, eptr);              GETCHARINC(c, eptr);
3828              prop_chartype = UCD_CHARTYPE(c);              prop_chartype = UCD_CHARTYPE(c);
3829              if ((prop_chartype == prop_value) == prop_fail_result)              if ((prop_chartype == prop_value) == prop_fail_result)
# Line 3454  for (;;) Line 3836  for (;;)
3836              {              {
3837              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40);              RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40);
3838              if (rrc != MATCH_NOMATCH) RRETURN(rrc);              if (rrc != MATCH_NOMATCH) RRETURN(rrc);
3839              if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);              if (fi >= max) RRETURN(MATCH_NOMATCH);
3840                if (eptr >= md->end_subject)
3841                  {
3842                  SCHECK_PARTIAL();
3843                  RRETURN(MATCH_NOMATCH);
3844                  }
3845              GETCHARINC(c, eptr);              GETCHARINC(c, eptr);
3846              prop_script = UCD_SCRIPT(c);              prop_script = UCD_SCRIPT(c);
3847              if ((prop_script == prop_value) == prop_fail_result)              if ((prop_script == prop_value) == prop_fail_result)
# Line 3476  for (;;) Line 3863  for (;;)
3863            {            {
3864            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41);
3865            if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
3866            if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);            if (fi >= max) RRETURN(MATCH_NOMATCH);
3867              if (eptr >= md->end_subject)
3868                {
3869                SCHECK_PARTIAL();
3870                RRETURN(MATCH_NOMATCH);
3871                }
3872            GETCHARINCTEST(c, eptr);            GETCHARINCTEST(c, eptr);
3873            prop_category = UCD_CATEGORY(c);            prop_category = UCD_CATEGORY(c);
3874            if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);            if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);
3875            while (eptr < md->end_subject)            while (eptr < md->end_subject)
3876              {              {
3877              int len = 1;              int len = 1;
3878              if (!utf8) c = *eptr; else              if (!utf8) c = *eptr;
3879                {                else { GETCHARLEN(c, eptr, len); }
               GETCHARLEN(c, eptr, len);  
               }  
3880              prop_category = UCD_CATEGORY(c);              prop_category = UCD_CATEGORY(c);
3881              if (prop_category != ucp_M) break;              if (prop_category != ucp_M) break;
3882              eptr += len;              eptr += len;
# Line 3505  for (;;) Line 3895  for (;;)
3895            {            {
3896            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42);
3897            if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
3898            if (fi >= max || eptr >= md->end_subject ||            if (fi >= max) RRETURN(MATCH_NOMATCH);
3899                 (ctype == OP_ANY && IS_NEWLINE(eptr)))            if (eptr >= md->end_subject)
3900                {
3901                SCHECK_PARTIAL();
3902                RRETURN(MATCH_NOMATCH);
3903                }
3904              if (ctype == OP_ANY && IS_NEWLINE(eptr))
3905              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
   
3906            GETCHARINC(c, eptr);            GETCHARINC(c, eptr);
3907            switch(ctype)            switch(ctype)
3908              {              {
# Line 3664  for (;;) Line 4058  for (;;)
4058            {            {
4059            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43);            RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43);
4060            if (rrc != MATCH_NOMATCH) RRETURN(rrc);            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
4061            if (fi >= max || eptr >= md->end_subject ||            if (fi >= max) RRETURN(MATCH_NOMATCH);
4062                 (ctype == OP_ANY && IS_NEWLINE(eptr)))            if (eptr >= md->end_subject)
4063                {
4064                SCHECK_PARTIAL();
4065                RRETURN(MATCH_NOMATCH);
4066                }
4067              if (ctype == OP_ANY && IS_NEWLINE(eptr))
4068              RRETURN(MATCH_NOMATCH);              RRETURN(MATCH_NOMATCH);
   
4069            c = *eptr++;            c = *eptr++;
4070            switch(ctype)            switch(ctype)
4071              {              {
# Line 4450  const uschar *tables; Line 4848  const uschar *tables;
4848  const uschar *start_bits = NULL;  const uschar *start_bits = NULL;
4849  USPTR start_match = (USPTR)subject + start_offset;  USPTR start_match = (USPTR)subject + start_offset;
4850  USPTR end_subject;  USPTR end_subject;
4851    USPTR start_partial = NULL;
4852  USPTR req_byte_ptr = start_match - 1;  USPTR req_byte_ptr = start_match - 1;
4853    
4854  pcre_study_data internal_study;  pcre_study_data internal_study;
# Line 4533  md->jscript_compat = (re->options & PCRE Line 4932  md->jscript_compat = (re->options & PCRE
4932  md->notbol = (options & PCRE_NOTBOL) != 0;  md->notbol = (options & PCRE_NOTBOL) != 0;
4933  md->noteol = (options & PCRE_NOTEOL) != 0;  md->noteol = (options & PCRE_NOTEOL) != 0;
4934  md->notempty = (options & PCRE_NOTEMPTY) != 0;  md->notempty = (options & PCRE_NOTEMPTY) != 0;
4935  md->partial = (options & PCRE_PARTIAL) != 0;  md->notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
4936    md->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 :
4937                  ((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0;
4938  md->hitend = FALSE;  md->hitend = FALSE;
4939    
4940  md->recursive = NULL;                   /* No recursion at top level */  md->recursive = NULL;                   /* No recursion at top level */
# Line 4607  else Line 5008  else
5008      }      }
5009    }    }
5010    
5011  /* Partial matching is supported only for a restricted set of regexes at the  /* Partial matching was originally supported only for a restricted set of
5012  moment. */  regexes; from release 8.00 there are no restrictions, but the bits are still
5013    defined (though never set). So there's no harm in leaving this code. */
5014    
5015  if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0)  if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0)
5016    return PCRE_ERROR_BADPARTIAL;    return PCRE_ERROR_BADPARTIAL;
# Line 4619  back the character offset. */ Line 5021  back the character offset. */
5021  #ifdef SUPPORT_UTF8  #ifdef SUPPORT_UTF8
5022  if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)  if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)
5023    {    {
5024    if (_pcre_valid_utf8((uschar *)subject, length) >= 0)    if (_pcre_valid_utf8((USPTR)subject, length) >= 0)
5025      return PCRE_ERROR_BADUTF8;      return PCRE_ERROR_BADUTF8;
5026    if (start_offset > 0 && start_offset < length)    if (start_offset > 0 && start_offset < length)
5027      {      {
5028      int tb = ((uschar *)subject)[start_offset];      int tb = ((USPTR)subject)[start_offset];
5029      if (tb > 127)      if (tb > 127)
5030        {        {
5031        tb &= 0xc0;        tb &= 0xc0;
# Line 4890  for(;;) Line 5292  for(;;)
5292        }        }
5293      }      }
5294    
5295    /* OK, we can now run the match. */    /* OK, we can now run the match. If "hitend" is set afterwards, remember the
5296      first starting point for which a partial match was found. */
5297    
5298    md->start_match_ptr = start_match;    md->start_match_ptr = start_match;
5299      md->start_used_ptr = start_match;
5300    md->match_call_count = 0;    md->match_call_count = 0;
5301    rc = match(start_match, md->start_code, start_match, 2, md, ims, NULL, 0, 0);    rc = match(start_match, md->start_code, start_match, 2, md, ims, NULL, 0, 0);
5302      if (md->hitend && start_partial == NULL) start_partial = md->start_used_ptr;
5303    
5304    switch(rc)    switch(rc)
5305      {      {
# Line 4924  for(;;) Line 5329  for(;;)
5329      rc = MATCH_NOMATCH;      rc = MATCH_NOMATCH;
5330      goto ENDLOOP;      goto ENDLOOP;
5331    
5332      /* Any other return is some kind of error. */      /* Any other return is either a match, or some kind of error. */
5333    
5334      default:      default:
5335      goto ENDLOOP;      goto ENDLOOP;
# Line 5006  if (rc == MATCH_MATCH) Line 5411  if (rc == MATCH_MATCH)
5411    too many to fit into the vector. */    too many to fit into the vector. */
5412    
5413    rc = md->offset_overflow? 0 : md->end_offset_top/2;    rc = md->offset_overflow? 0 : md->end_offset_top/2;
5414    
5415    /* If there is space, set up the whole thing as substring 0. The value of    /* If there is space, set up the whole thing as substring 0. The value of
5416    md->start_match_ptr might be modified if \K was encountered on the success    md->start_match_ptr might be modified if \K was encountered on the success
5417    matching path. */    matching path. */
# Line 5030  if (using_temporary_offsets) Line 5435  if (using_temporary_offsets)
5435    (pcre_free)(md->offset_vector);    (pcre_free)(md->offset_vector);
5436    }    }
5437    
5438  if (rc != MATCH_NOMATCH)  if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL)
5439    {    {
5440    DPRINTF((">>>> error: returning %d\n", rc));    DPRINTF((">>>> error: returning %d\n", rc));
5441    return rc;    return rc;
5442    }    }
5443  else if (md->partial && md->hitend)  else if (start_partial != NULL)
5444    {    {
5445    DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));    DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));
5446      if (offsetcount > 1)
5447        {
5448        offsets[0] = start_partial - (USPTR)subject;
5449        offsets[1] = end_subject - (USPTR)subject;
5450        }
5451    return PCRE_ERROR_PARTIAL;    return PCRE_ERROR_PARTIAL;
5452    }    }
5453  else  else

Legend:
Removed from v.403  
changed lines
  Added in v.446

  ViewVC Help
Powered by ViewVC 1.1.5