|
|
| version 1.2, 2009/04/10 12:53:37 | version 1.5, 2011/02/01 05:03:42 |
|---|---|
| Line 6 | Line 6 |
| and semantics are as close as possible to those of the Perl 5 language. | and semantics are as close as possible to those of the Perl 5 language. |
| Written by Philip Hazel | Written by Philip Hazel |
| Copyright (c) 1997-2008 University of Cambridge | Copyright (c) 1997-2010 University of Cambridge |
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| Redistribution and use in source and binary forms, with or without | Redistribution and use in source and binary forms, with or without |
| Line 71 defined PCRE_ERROR_xxx codes, which are | Line 71 defined PCRE_ERROR_xxx codes, which are |
| /* Special internal returns from the match() function. Make them sufficiently | /* Special internal returns from the match() function. Make them sufficiently |
| negative to avoid the external error codes. */ | negative to avoid the external error codes. */ |
| #define MATCH_COMMIT (-999) | #define MATCH_ACCEPT (-999) |
| #define MATCH_PRUNE (-998) | #define MATCH_COMMIT (-998) |
| #define MATCH_SKIP (-997) | #define MATCH_PRUNE (-997) |
| #define MATCH_THEN (-996) | #define MATCH_SKIP (-996) |
| #define MATCH_SKIP_ARG (-995) | |
| #define MATCH_THEN (-994) | |
| /* This is a convenience macro for code that occurs many times. */ | |
| #define MRRETURN(ra) \ | |
| { \ | |
| md->mark = markptr; \ | |
| RRETURN(ra); \ | |
| } | |
| /* Maximum number of ints of offset to save on the stack for recursive calls. | /* Maximum number of ints of offset to save on the stack for recursive calls. |
| If the offset vector is bigger, malloc is used. This should be a multiple of 3, | If the offset vector is bigger, malloc is used. This should be a multiple of 3, |
| Line 89 static const char rep_max[] = { 0, 0, 0, | Line 99 static const char rep_max[] = { 0, 0, 0, |
| #ifdef DEBUG | #ifdef PCRE_DEBUG |
| /************************************************* | /************************************************* |
| * Debugging function to print chars * | * Debugging function to print chars * |
| *************************************************/ | *************************************************/ |
| Line 141 match_ref(int offset, register USPTR ept | Line 151 match_ref(int offset, register USPTR ept |
| { | { |
| USPTR p = md->start_subject + md->offset_vector[offset]; | USPTR p = md->start_subject + md->offset_vector[offset]; |
| #ifdef DEBUG | #ifdef PCRE_DEBUG |
| if (eptr >= md->end_subject) | if (eptr >= md->end_subject) |
| printf("matching subject <null>"); | printf("matching subject <null>"); |
| else | else |
| Line 245 enum { RM1=1, RM2, RM3, RM4, RM5, RM | Line 255 enum { RM1=1, RM2, RM3, RM4, RM5, RM |
| RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30, | RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30, |
| RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40, | RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40, |
| RM41, RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50, | RM41, RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50, |
| RM51, RM52, RM53, RM54 }; | RM51, RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60, |
| RM61, RM62 }; | |
| /* These versions of the macros use the stack, as normal. There are debugging | /* These versions of the macros use the stack, as normal. There are debugging |
| versions and production versions. Note that the "rw" argument of RMATCH isn't | versions and production versions. Note that the "rw" argument of RMATCH isn't |
| actuall used in this definition. */ | actually used in this definition. */ |
| #ifndef NO_RECURSE | #ifndef NO_RECURSE |
| #define REGISTER register | #define REGISTER register |
| #ifdef DEBUG | #ifdef PCRE_DEBUG |
| #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \ | #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \ |
| { \ | { \ |
| printf("match() called in line %d\n", __LINE__); \ | printf("match() called in line %d\n", __LINE__); \ |
| rrc = match(ra,rb,mstart,rc,rd,re,rf,rg,rdepth+1); \ | rrc = match(ra,rb,mstart,markptr,rc,rd,re,rf,rg,rdepth+1); \ |
| printf("to line %d\n", __LINE__); \ | printf("to line %d\n", __LINE__); \ |
| } | } |
| #define RRETURN(ra) \ | #define RRETURN(ra) \ |
| Line 268 actuall used in this definition. */ | Line 279 actuall used in this definition. */ |
| } | } |
| #else | #else |
| #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \ | #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \ |
| rrc = match(ra,rb,mstart,rc,rd,re,rf,rg,rdepth+1) | rrc = match(ra,rb,mstart,markptr,rc,rd,re,rf,rg,rdepth+1) |
| #define RRETURN(ra) return ra | #define RRETURN(ra) return ra |
| #endif | #endif |
| Line 283 argument of match(), which never changes | Line 294 argument of match(), which never changes |
| #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw)\ | #define RMATCH(ra,rb,rc,rd,re,rf,rg,rw)\ |
| {\ | {\ |
| heapframe *newframe = (pcre_stack_malloc)(sizeof(heapframe));\ | heapframe *newframe = (heapframe *)(pcre_stack_malloc)(sizeof(heapframe));\ |
| if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\ | |
| frame->Xwhere = rw; \ | frame->Xwhere = rw; \ |
| newframe->Xeptr = ra;\ | newframe->Xeptr = ra;\ |
| newframe->Xecode = rb;\ | newframe->Xecode = rb;\ |
| newframe->Xmstart = mstart;\ | newframe->Xmstart = mstart;\ |
| newframe->Xmarkptr = markptr;\ | |
| newframe->Xoffset_top = rc;\ | newframe->Xoffset_top = rc;\ |
| newframe->Xims = re;\ | newframe->Xims = re;\ |
| newframe->Xeptrb = rf;\ | newframe->Xeptrb = rf;\ |
| Line 303 argument of match(), which never changes | Line 316 argument of match(), which never changes |
| #define RRETURN(ra)\ | #define RRETURN(ra)\ |
| {\ | {\ |
| heapframe *newframe = frame;\ | heapframe *oldframe = frame;\ |
| frame = newframe->Xprevframe;\ | frame = oldframe->Xprevframe;\ |
| (pcre_stack_free)(newframe);\ | (pcre_stack_free)(oldframe);\ |
| if (frame != NULL)\ | if (frame != NULL)\ |
| {\ | {\ |
| rrc = ra;\ | rrc = ra;\ |
| Line 322 typedef struct heapframe { | Line 335 typedef struct heapframe { |
| /* Function arguments that may change */ | /* Function arguments that may change */ |
| const uschar *Xeptr; | USPTR Xeptr; |
| const uschar *Xecode; | const uschar *Xecode; |
| const uschar *Xmstart; | USPTR Xmstart; |
| USPTR Xmarkptr; | |
| int Xoffset_top; | int Xoffset_top; |
| long int Xims; | long int Xims; |
| eptrblock *Xeptrb; | eptrblock *Xeptrb; |
| Line 333 typedef struct heapframe { | Line 347 typedef struct heapframe { |
| /* Function local variables */ | /* Function local variables */ |
| const uschar *Xcallpat; | USPTR Xcallpat; |
| const uschar *Xcharptr; | #ifdef SUPPORT_UTF8 |
| const uschar *Xdata; | USPTR Xcharptr; |
| const uschar *Xnext; | #endif |
| const uschar *Xpp; | USPTR Xdata; |
| const uschar *Xprev; | USPTR Xnext; |
| const uschar *Xsaved_eptr; | USPTR Xpp; |
| USPTR Xprev; | |
| USPTR Xsaved_eptr; | |
| recursion_info Xnew_recursive; | recursion_info Xnew_recursive; |
| Line 360 typedef struct heapframe { | Line 376 typedef struct heapframe { |
| uschar Xocchars[8]; | uschar Xocchars[8]; |
| #endif | #endif |
| int Xcodelink; | |
| int Xctype; | int Xctype; |
| unsigned int Xfc; | unsigned int Xfc; |
| int Xfi; | int Xfi; |
| Line 395 typedef struct heapframe { | Line 412 typedef struct heapframe { |
| /* This function is called recursively in many circumstances. Whenever it | /* This function is called recursively in many circumstances. Whenever it |
| returns a negative (error) response, the outer incarnation must also return the | returns a negative (error) response, the outer incarnation must also return the |
| same response. | same response. */ |
| Performance note: It might be tempting to extract commonly used fields from the | /* These macros pack up tests that are used for partial matching, and which |
| md structure (e.g. utf8, end_subject) into individual variables to improve | appears several times in the code. We set the "hit end" flag if the pointer is |
| at the end of the subject and also past the start of the subject (i.e. | |
| something has been matched). For hard partial matching, we then return | |
| immediately. The second one is used when we already know we are past the end of | |
| the subject. */ | |
| #define CHECK_PARTIAL()\ | |
| if (md->partial != 0 && eptr >= md->end_subject && \ | |
| eptr > md->start_used_ptr) \ | |
| { \ | |
| md->hitend = TRUE; \ | |
| if (md->partial > 1) MRRETURN(PCRE_ERROR_PARTIAL); \ | |
| } | |
| #define SCHECK_PARTIAL()\ | |
| if (md->partial != 0 && eptr > md->start_used_ptr) \ | |
| { \ | |
| md->hitend = TRUE; \ | |
| if (md->partial > 1) MRRETURN(PCRE_ERROR_PARTIAL); \ | |
| } | |
| /* Performance note: It might be tempting to extract commonly used fields from | |
| the md structure (e.g. utf8, end_subject) into individual variables to improve | |
| 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 |
| made performance worse. | made performance worse. |
| Line 407 Arguments: | Line 447 Arguments: |
| ecode pointer to current position in compiled code | ecode pointer to current position in compiled code |
| mstart pointer to the current match start position (can be modified | mstart pointer to the current match start position (can be modified |
| by encountering \K) | by encountering \K) |
| markptr pointer to the most recent MARK name, or NULL | |
| offset_top current top pointer | offset_top current top pointer |
| md pointer to "static" info for the match | md pointer to "static" info for the match |
| ims current /i, /m, and /s options | ims current /i, /m, and /s options |
| Line 420 Arguments: | Line 461 Arguments: |
| Returns: MATCH_MATCH if matched ) these values are >= 0 | Returns: MATCH_MATCH if matched ) these values are >= 0 |
| MATCH_NOMATCH if failed to match ) | MATCH_NOMATCH if failed to match ) |
| a negative MATCH_xxx value for PRUNE, SKIP, etc | |
| a negative PCRE_ERROR_xxx value if aborted by an error condition | a negative PCRE_ERROR_xxx value if aborted by an error condition |
| (e.g. stopped by repeated call or recursion limit) | (e.g. stopped by repeated call or recursion limit) |
| */ | */ |
| static int | static int |
| match(REGISTER USPTR eptr, REGISTER const uschar *ecode, const uschar *mstart, | match(REGISTER USPTR eptr, REGISTER const uschar *ecode, USPTR mstart, |
| int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb, | const uschar *markptr, int offset_top, match_data *md, unsigned long int ims, |
| int flags, unsigned int rdepth) | eptrblock *eptrb, int flags, unsigned int rdepth) |
| { | { |
| /* These variables do not need to be preserved over recursion in this function, | /* These variables do not need to be preserved over recursion in this function, |
| so they can be ordinary variables in all cases. Mark some of them with | so they can be ordinary variables in all cases. Mark some of them with |
| Line 439 register unsigned int c; /* Character | Line 481 register unsigned int c; /* Character |
| register BOOL utf8; /* Local copy of UTF-8 flag for speed */ | register BOOL utf8; /* Local copy of UTF-8 flag for speed */ |
| BOOL minimize, possessive; /* Quantifier options */ | BOOL minimize, possessive; /* Quantifier options */ |
| int condcode; | |
| /* When recursion is not being used, all "local" variables that have to be | /* When recursion is not being used, all "local" variables that have to be |
| preserved over calls to RMATCH() are part of a "frame" which is obtained from | preserved over calls to RMATCH() are part of a "frame" which is obtained from |
| Line 446 heap storage. Set up the top-level frame | Line 489 heap storage. Set up the top-level frame |
| heap whenever RMATCH() does a "recursion". See the macro definitions above. */ | heap whenever RMATCH() does a "recursion". See the macro definitions above. */ |
| #ifdef NO_RECURSE | #ifdef NO_RECURSE |
| heapframe *frame = (pcre_stack_malloc)(sizeof(heapframe)); | heapframe *frame = (heapframe *)(pcre_stack_malloc)(sizeof(heapframe)); |
| if (frame == NULL) RRETURN(PCRE_ERROR_NOMEMORY); | |
| frame->Xprevframe = NULL; /* Marks the top level */ | frame->Xprevframe = NULL; /* Marks the top level */ |
| /* Copy in the original argument variables */ | /* Copy in the original argument variables */ |
| Line 454 frame->Xprevframe = NULL; /* | Line 498 frame->Xprevframe = NULL; /* |
| frame->Xeptr = eptr; | frame->Xeptr = eptr; |
| frame->Xecode = ecode; | frame->Xecode = ecode; |
| frame->Xmstart = mstart; | frame->Xmstart = mstart; |
| frame->Xmarkptr = markptr; | |
| frame->Xoffset_top = offset_top; | frame->Xoffset_top = offset_top; |
| frame->Xims = ims; | frame->Xims = ims; |
| frame->Xeptrb = eptrb; | frame->Xeptrb = eptrb; |
| Line 469 HEAP_RECURSE: | Line 514 HEAP_RECURSE: |
| #define eptr frame->Xeptr | #define eptr frame->Xeptr |
| #define ecode frame->Xecode | #define ecode frame->Xecode |
| #define mstart frame->Xmstart | #define mstart frame->Xmstart |
| #define markptr frame->Xmarkptr | |
| #define offset_top frame->Xoffset_top | #define offset_top frame->Xoffset_top |
| #define ims frame->Xims | #define ims frame->Xims |
| #define eptrb frame->Xeptrb | #define eptrb frame->Xeptrb |
| Line 481 HEAP_RECURSE: | Line 527 HEAP_RECURSE: |
| #define charptr frame->Xcharptr | #define charptr frame->Xcharptr |
| #endif | #endif |
| #define callpat frame->Xcallpat | #define callpat frame->Xcallpat |
| #define codelink frame->Xcodelink | |
| #define data frame->Xdata | #define data frame->Xdata |
| #define next frame->Xnext | #define next frame->Xnext |
| #define pp frame->Xpp | #define pp frame->Xpp |
| Line 561 int oclength; | Line 608 int oclength; |
| uschar occhars[8]; | uschar occhars[8]; |
| #endif | #endif |
| int codelink; | |
| int ctype; | int ctype; |
| int length; | int length; |
| int max; | int max; |
| Line 594 TAIL_RECURSE: | Line 642 TAIL_RECURSE: |
| /* OK, now we can get on with the real code of the function. Recursive calls | /* OK, now we can get on with the real code of the function. Recursive calls |
| are specified by the macro RMATCH and RRETURN is used to return. When | are specified by the macro RMATCH and RRETURN is used to return. When |
| NO_RECURSE is *not* defined, these just turn into a recursive call to match() | NO_RECURSE is *not* defined, these just turn into a recursive call to match() |
| and a "return", respectively (possibly with some debugging if DEBUG is | and a "return", respectively (possibly with some debugging if PCRE_DEBUG is |
| defined). However, RMATCH isn't like a function call because it's quite a | defined). However, RMATCH isn't like a function call because it's quite a |
| complicated macro. It has to be used in one particular way. This shouldn't, | complicated macro. It has to be used in one particular way. This shouldn't, |
| however, impact performance when true recursion is being used. */ | however, impact performance when true recursion is being used. */ |
| Line 636 for (;;) | Line 684 for (;;) |
| minimize = possessive = FALSE; | minimize = possessive = FALSE; |
| 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; | |
| switch(op) | switch(op) |
| { | { |
| case OP_MARK: | |
| markptr = ecode + 2; | |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md, | |
| ims, eptrb, flags, RM55); | |
| /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an | |
| argument, and we must check whether that argument matches this MARK's | |
| argument. It is passed back in md->start_match_ptr (an overloading of that | |
| variable). If it does match, we reset that variable to the current subject | |
| position and return MATCH_SKIP. Otherwise, pass back the return code | |
| unaltered. */ | |
| if (rrc == MATCH_SKIP_ARG && | |
| strcmp((char *)markptr, (char *)(md->start_match_ptr)) == 0) | |
| { | |
| md->start_match_ptr = eptr; | |
| RRETURN(MATCH_SKIP); | |
| } | |
| if (md->mark == NULL) md->mark = markptr; | |
| RRETURN(rrc); | |
| case OP_FAIL: | case OP_FAIL: |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| /* COMMIT overrides PRUNE, SKIP, and THEN */ | |
| case OP_COMMIT: | |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, | |
| ims, eptrb, flags, RM52); | |
| if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && | |
| rrc != MATCH_SKIP && rrc != MATCH_SKIP_ARG && | |
| rrc != MATCH_THEN) | |
| RRETURN(rrc); | |
| MRRETURN(MATCH_COMMIT); | |
| /* PRUNE overrides THEN */ | |
| case OP_PRUNE: | case OP_PRUNE: |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, | RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, |
| ims, eptrb, flags, RM51); | ims, eptrb, flags, RM51); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); |
| MRRETURN(MATCH_PRUNE); | |
| case OP_PRUNE_ARG: | |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md, | |
| ims, eptrb, flags, RM56); | |
| if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); | |
| md->mark = ecode + 2; | |
| RRETURN(MATCH_PRUNE); | RRETURN(MATCH_PRUNE); |
| case OP_COMMIT: | /* SKIP overrides PRUNE and THEN */ |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, | |
| ims, eptrb, flags, RM52); | |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | |
| RRETURN(MATCH_COMMIT); | |
| case OP_SKIP: | case OP_SKIP: |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, | RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, |
| ims, eptrb, flags, RM53); | ims, eptrb, flags, RM53); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN) |
| RRETURN(rrc); | |
| md->start_match_ptr = eptr; /* Pass back current position */ | md->start_match_ptr = eptr; /* Pass back current position */ |
| RRETURN(MATCH_SKIP); | MRRETURN(MATCH_SKIP); |
| case OP_SKIP_ARG: | |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md, | |
| ims, eptrb, flags, RM57); | |
| if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN) | |
| RRETURN(rrc); | |
| /* Pass back the current skip name by overloading md->start_match_ptr and | |
| returning the special MATCH_SKIP_ARG return code. This will either be | |
| caught by a matching MARK, or get to the top, where it is treated the same | |
| as PRUNE. */ | |
| md->start_match_ptr = ecode + 2; | |
| RRETURN(MATCH_SKIP_ARG); | |
| /* For THEN (and THEN_ARG) we pass back the address of the bracket or | |
| the alt that is at the start of the current branch. This makes it possible | |
| to skip back past alternatives that precede the THEN within the current | |
| branch. */ | |
| case OP_THEN: | case OP_THEN: |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, | RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, |
| ims, eptrb, flags, RM54); | ims, eptrb, flags, RM54); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| md->start_match_ptr = ecode - GET(ecode, 1); | |
| MRRETURN(MATCH_THEN); | |
| case OP_THEN_ARG: | |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1+LINK_SIZE], | |
| offset_top, md, ims, eptrb, flags, RM58); | |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | |
| md->start_match_ptr = ecode - GET(ecode, 1); | |
| md->mark = ecode + LINK_SIZE + 2; | |
| RRETURN(MATCH_THEN); | RRETURN(MATCH_THEN); |
| /* Handle a capturing bracket. If there is space in the offset vector, save | /* Handle a capturing bracket. If there is space in the offset vector, save |
| Line 693 for (;;) | Line 800 for (;;) |
| number = GET2(ecode, 1+LINK_SIZE); | number = GET2(ecode, 1+LINK_SIZE); |
| offset = number << 1; | offset = number << 1; |
| #ifdef DEBUG | #ifdef PCRE_DEBUG |
| printf("start bracket %d\n", number); | printf("start bracket %d\n", number); |
| printf("subject="); | printf("subject="); |
| pchars(eptr, 16, TRUE, md); | pchars(eptr, 16, TRUE, md); |
| Line 708 for (;;) | Line 815 for (;;) |
| save_capture_last = md->capture_last; | save_capture_last = md->capture_last; |
| DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); | DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); |
| md->offset_vector[md->offset_end - number] = eptr - md->start_subject; | md->offset_vector[md->offset_end - number] = |
| (int)(eptr - md->start_subject); | |
| flags = (op == OP_SCBRA)? match_cbegroup : 0; | flags = (op == OP_SCBRA)? match_cbegroup : 0; |
| do | do |
| { | { |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, | RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, |
| ims, eptrb, flags, RM1); | ims, eptrb, flags, RM1); |
| if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); | if (rrc != MATCH_NOMATCH && |
| (rrc != MATCH_THEN || md->start_match_ptr != ecode)) | |
| RRETURN(rrc); | |
| md->capture_last = save_capture_last; | md->capture_last = save_capture_last; |
| ecode += GET(ecode, 1); | ecode += GET(ecode, 1); |
| } | } |
| Line 727 for (;;) | Line 837 for (;;) |
| md->offset_vector[offset+1] = save_offset2; | md->offset_vector[offset+1] = save_offset2; |
| md->offset_vector[md->offset_end - number] = save_offset3; | md->offset_vector[md->offset_end - number] = save_offset3; |
| if (rrc != MATCH_THEN) md->mark = markptr; | |
| RRETURN(MATCH_NOMATCH); | RRETURN(MATCH_NOMATCH); |
| } | } |
| Line 766 for (;;) | Line 877 for (;;) |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims, | RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims, |
| eptrb, flags, RM48); | eptrb, flags, RM48); |
| if (rrc == MATCH_NOMATCH) md->mark = markptr; | |
| RRETURN(rrc); | RRETURN(rrc); |
| } | } |
| Line 774 for (;;) | Line 886 for (;;) |
| RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims, | RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims, |
| eptrb, flags, RM2); | eptrb, flags, RM2); |
| if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); | if (rrc != MATCH_NOMATCH && |
| (rrc != MATCH_THEN || md->start_match_ptr != ecode)) | |
| RRETURN(rrc); | |
| ecode += GET(ecode, 1); | ecode += GET(ecode, 1); |
| } | } |
| /* Control never reaches here. */ | /* Control never reaches here. */ |
| Line 787 for (;;) | Line 901 for (;;) |
| case OP_COND: | case OP_COND: |
| case OP_SCOND: | case OP_SCOND: |
| if (ecode[LINK_SIZE+1] == OP_RREF) /* Recursion test */ | codelink= GET(ecode, 1); |
| /* Because of the way auto-callout works during compile, a callout item is | |
| inserted between OP_COND and an assertion condition. */ | |
| if (ecode[LINK_SIZE+1] == OP_CALLOUT) | |
| { | { |
| offset = GET2(ecode, LINK_SIZE + 2); /* Recursion group number*/ | if (pcre_callout != NULL) |
| condition = md->recursive != NULL && | { |
| (offset == RREF_ANY || offset == md->recursive->group_num); | pcre_callout_block cb; |
| ecode += condition? 3 : GET(ecode, 1); | cb.version = 1; /* Version 1 of the callout block */ |
| cb.callout_number = ecode[LINK_SIZE+2]; | |
| cb.offset_vector = md->offset_vector; | |
| cb.subject = (PCRE_SPTR)md->start_subject; | |
| cb.subject_length = (int)(md->end_subject - md->start_subject); | |
| cb.start_match = (int)(mstart - md->start_subject); | |
| cb.current_position = (int)(eptr - md->start_subject); | |
| cb.pattern_position = GET(ecode, LINK_SIZE + 3); | |
| cb.next_item_length = GET(ecode, 3 + 2*LINK_SIZE); | |
| cb.capture_top = offset_top/2; | |
| cb.capture_last = md->capture_last; | |
| cb.callout_data = md->callout_data; | |
| if ((rrc = (*pcre_callout)(&cb)) > 0) MRRETURN(MATCH_NOMATCH); | |
| if (rrc < 0) RRETURN(rrc); | |
| } | |
| ecode += _pcre_OP_lengths[OP_CALLOUT]; | |
| } | |
| condcode = ecode[LINK_SIZE+1]; | |
| /* Now see what the actual condition is */ | |
| if (condcode == OP_RREF || condcode == OP_NRREF) /* Recursion test */ | |
| { | |
| if (md->recursive == NULL) /* Not recursing => FALSE */ | |
| { | |
| condition = FALSE; | |
| ecode += GET(ecode, 1); | |
| } | |
| else | |
| { | |
| int recno = GET2(ecode, LINK_SIZE + 2); /* Recursion group number*/ | |
| condition = (recno == RREF_ANY || recno == md->recursive->group_num); | |
| /* If the test is for recursion into a specific subpattern, and it is | |
| false, but the test was set up by name, scan the table to see if the | |
| name refers to any other numbers, and test them. The condition is true | |
| if any one is set. */ | |
| if (!condition && condcode == OP_NRREF && recno != RREF_ANY) | |
| { | |
| uschar *slotA = md->name_table; | |
| for (i = 0; i < md->name_count; i++) | |
| { | |
| if (GET2(slotA, 0) == recno) break; | |
| slotA += md->name_entry_size; | |
| } | |
| /* Found a name for the number - there can be only one; duplicate | |
| names for different numbers are allowed, but not vice versa. First | |
| scan down for duplicates. */ | |
| if (i < md->name_count) | |
| { | |
| uschar *slotB = slotA; | |
| while (slotB > md->name_table) | |
| { | |
| slotB -= md->name_entry_size; | |
| if (strcmp((char *)slotA + 2, (char *)slotB + 2) == 0) | |
| { | |
| condition = GET2(slotB, 0) == md->recursive->group_num; | |
| if (condition) break; | |
| } | |
| else break; | |
| } | |
| /* Scan up for duplicates */ | |
| if (!condition) | |
| { | |
| slotB = slotA; | |
| for (i++; i < md->name_count; i++) | |
| { | |
| slotB += md->name_entry_size; | |
| if (strcmp((char *)slotA + 2, (char *)slotB + 2) == 0) | |
| { | |
| condition = GET2(slotB, 0) == md->recursive->group_num; | |
| if (condition) break; | |
| } | |
| else break; | |
| } | |
| } | |
| } | |
| } | |
| /* Chose branch according to the condition */ | |
| ecode += condition? 3 : GET(ecode, 1); | |
| } | |
| } | } |
| else if (ecode[LINK_SIZE+1] == OP_CREF) /* Group used test */ | else if (condcode == OP_CREF || condcode == OP_NCREF) /* Group used test */ |
| { | { |
| offset = GET2(ecode, LINK_SIZE+2) << 1; /* Doubled ref number */ | offset = GET2(ecode, LINK_SIZE+2) << 1; /* Doubled ref number */ |
| condition = offset < offset_top && md->offset_vector[offset] >= 0; | condition = offset < offset_top && md->offset_vector[offset] >= 0; |
| /* If the numbered capture is unset, but the reference was by name, | |
| scan the table to see if the name refers to any other numbers, and test | |
| them. The condition is true if any one is set. This is tediously similar | |
| to the code above, but not close enough to try to amalgamate. */ | |
| if (!condition && condcode == OP_NCREF) | |
| { | |
| int refno = offset >> 1; | |
| uschar *slotA = md->name_table; | |
| for (i = 0; i < md->name_count; i++) | |
| { | |
| if (GET2(slotA, 0) == refno) break; | |
| slotA += md->name_entry_size; | |
| } | |
| /* Found a name for the number - there can be only one; duplicate names | |
| for different numbers are allowed, but not vice versa. First scan down | |
| for duplicates. */ | |
| if (i < md->name_count) | |
| { | |
| uschar *slotB = slotA; | |
| while (slotB > md->name_table) | |
| { | |
| slotB -= md->name_entry_size; | |
| if (strcmp((char *)slotA + 2, (char *)slotB + 2) == 0) | |
| { | |
| offset = GET2(slotB, 0) << 1; | |
| condition = offset < offset_top && | |
| md->offset_vector[offset] >= 0; | |
| if (condition) break; | |
| } | |
| else break; | |
| } | |
| /* Scan up for duplicates */ | |
| if (!condition) | |
| { | |
| slotB = slotA; | |
| for (i++; i < md->name_count; i++) | |
| { | |
| slotB += md->name_entry_size; | |
| if (strcmp((char *)slotA + 2, (char *)slotB + 2) == 0) | |
| { | |
| offset = GET2(slotB, 0) << 1; | |
| condition = offset < offset_top && | |
| md->offset_vector[offset] >= 0; | |
| if (condition) break; | |
| } | |
| else break; | |
| } | |
| } | |
| } | |
| } | |
| /* Chose branch according to the condition */ | |
| ecode += condition? 3 : GET(ecode, 1); | ecode += condition? 3 : GET(ecode, 1); |
| } | } |
| else if (ecode[LINK_SIZE+1] == OP_DEF) /* DEFINE - always false */ | else if (condcode == OP_DEF) /* DEFINE - always false */ |
| { | { |
| condition = FALSE; | condition = FALSE; |
| ecode += GET(ecode, 1); | ecode += GET(ecode, 1); |
| Line 822 for (;;) | Line 1089 for (;;) |
| ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2); | ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2); |
| while (*ecode == OP_ALT) ecode += GET(ecode, 1); | while (*ecode == OP_ALT) ecode += GET(ecode, 1); |
| } | } |
| else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) | else if (rrc != MATCH_NOMATCH && |
| (rrc != MATCH_THEN || md->start_match_ptr != ecode)) | |
| { | { |
| RRETURN(rrc); /* Need braces because of following else */ | RRETURN(rrc); /* Need braces because of following else */ |
| } | } |
| else | else |
| { | { |
| condition = FALSE; | condition = FALSE; |
| ecode += GET(ecode, 1); | ecode += codelink; |
| } | } |
| } | } |
| Line 852 for (;;) | Line 1120 for (;;) |
| goto TAIL_RECURSE; | goto TAIL_RECURSE; |
| } | } |
| } | } |
| else /* Condition false & no 2nd alternative */ | else /* Condition false & no alternative */ |
| { | { |
| ecode += 1 + LINK_SIZE; | ecode += 1 + LINK_SIZE; |
| } | } |
| break; | break; |
| /* Before OP_ACCEPT there may be any number of OP_CLOSE opcodes, | |
| to close any currently open capturing brackets. */ | |
| case OP_CLOSE: | |
| number = GET2(ecode, 1); | |
| offset = number << 1; | |
| #ifdef PCRE_DEBUG | |
| printf("end bracket %d at *ACCEPT", number); | |
| printf("\n"); | |
| #endif | |
| md->capture_last = number; | |
| if (offset >= md->offset_max) md->offset_overflow = TRUE; else | |
| { | |
| md->offset_vector[offset] = | |
| md->offset_vector[md->offset_end - number]; | |
| md->offset_vector[offset+1] = (int)(eptr - md->start_subject); | |
| if (offset_top <= offset) offset_top = offset + 2; | |
| } | |
| ecode += 3; | |
| break; | |
| /* End of the pattern, either real or forced. If we are in a top-level | /* End of the pattern, either real or forced. If we are in a top-level |
| recursion, we should restore the offsets appropriately and continue from | recursion, we should restore the offsets appropriately and continue from |
| after the call. */ | after the call. */ |
| Line 872 for (;;) | Line 1164 for (;;) |
| md->recursive = rec->prevrec; | md->recursive = rec->prevrec; |
| memmove(md->offset_vector, rec->offset_save, | memmove(md->offset_vector, rec->offset_save, |
| rec->saved_max * sizeof(int)); | rec->saved_max * sizeof(int)); |
| mstart = rec->save_start; | offset_top = rec->save_offset_top; |
| ims = original_ims; | ims = original_ims; |
| ecode = rec->after_call; | ecode = rec->after_call; |
| break; | break; |
| } | } |
| /* 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 |
| 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 |
| the subject. In both cases, backtracking will then try other alternatives, | |
| if any. */ | |
| if (eptr == mstart && | |
| (md->notempty || | |
| (md->notempty_atstart && | |
| mstart == md->start_subject + md->start_offset))) | |
| MRRETURN(MATCH_NOMATCH); | |
| /* Otherwise, we have a match. */ | |
| if (md->notempty && eptr == mstart) RRETURN(MATCH_NOMATCH); | |
| md->end_match_ptr = eptr; /* Record where we ended */ | md->end_match_ptr = eptr; /* Record where we ended */ |
| md->end_offset_top = offset_top; /* and how many extracts were taken */ | md->end_offset_top = offset_top; /* and how many extracts were taken */ |
| md->start_match_ptr = mstart; /* and the start (\K can modify) */ | md->start_match_ptr = mstart; /* and the start (\K can modify) */ |
| RRETURN(MATCH_MATCH); | |
| /* For some reason, the macros don't work properly if an expression is | |
| given as the argument to MRRETURN when the heap is in use. */ | |
| rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT; | |
| MRRETURN(rrc); | |
| /* Change option settings */ | /* Change option settings */ |
| Line 907 for (;;) | Line 1213 for (;;) |
| { | { |
| RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0, | RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0, |
| RM4); | RM4); |
| if (rrc == MATCH_MATCH) break; | if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) |
| if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); | { |
| mstart = md->start_match_ptr; /* In case \K reset it */ | |
| break; | |
| } | |
| if (rrc != MATCH_NOMATCH && | |
| (rrc != MATCH_THEN || md->start_match_ptr != ecode)) | |
| RRETURN(rrc); | |
| ecode += GET(ecode, 1); | ecode += GET(ecode, 1); |
| } | } |
| while (*ecode == OP_ALT); | while (*ecode == OP_ALT); |
| if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH); | if (*ecode == OP_KET) MRRETURN(MATCH_NOMATCH); |
| /* If checking an assertion for a condition, return MATCH_MATCH. */ | /* If checking an assertion for a condition, return MATCH_MATCH. */ |
| Line 926 for (;;) | Line 1238 for (;;) |
| offset_top = md->end_offset_top; | offset_top = md->end_offset_top; |
| continue; | continue; |
| /* Negative assertion: all branches must fail to match */ | /* Negative assertion: all branches must fail to match. Encountering SKIP, |
| PRUNE, or COMMIT means we must assume failure without checking subsequent | |
| branches. */ | |
| case OP_ASSERT_NOT: | case OP_ASSERT_NOT: |
| case OP_ASSERTBACK_NOT: | case OP_ASSERTBACK_NOT: |
| Line 934 for (;;) | Line 1248 for (;;) |
| { | { |
| RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0, | RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0, |
| RM5); | RM5); |
| if (rrc == MATCH_MATCH) RRETURN(MATCH_NOMATCH); | if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) MRRETURN(MATCH_NOMATCH); |
| if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); | if (rrc == MATCH_SKIP || rrc == MATCH_PRUNE || rrc == MATCH_COMMIT) |
| { | |
| do ecode += GET(ecode,1); while (*ecode == OP_ALT); | |
| break; | |
| } | |
| if (rrc != MATCH_NOMATCH && | |
| (rrc != MATCH_THEN || md->start_match_ptr != ecode)) | |
| RRETURN(rrc); | |
| ecode += GET(ecode,1); | ecode += GET(ecode,1); |
| } | } |
| while (*ecode == OP_ALT); | while (*ecode == OP_ALT); |
| Line 958 for (;;) | Line 1279 for (;;) |
| while (i-- > 0) | while (i-- > 0) |
| { | { |
| eptr--; | eptr--; |
| if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); | if (eptr < md->start_subject) MRRETURN(MATCH_NOMATCH); |
| BACKCHAR(eptr); | BACKCHAR(eptr); |
| } | } |
| } | } |
| Line 969 for (;;) | Line 1290 for (;;) |
| { | { |
| eptr -= GET(ecode, 1); | eptr -= GET(ecode, 1); |
| if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); | if (eptr < md->start_subject) MRRETURN(MATCH_NOMATCH); |
| } | } |
| /* Skip to next op code */ | /* Save the earliest consulted character, then skip to next op code */ |
| if (eptr < md->start_used_ptr) md->start_used_ptr = eptr; | |
| ecode += 1 + LINK_SIZE; | ecode += 1 + LINK_SIZE; |
| break; | break; |
| Line 989 for (;;) | Line 1311 for (;;) |
| cb.callout_number = ecode[1]; | cb.callout_number = ecode[1]; |
| cb.offset_vector = md->offset_vector; | cb.offset_vector = md->offset_vector; |
| cb.subject = (PCRE_SPTR)md->start_subject; | cb.subject = (PCRE_SPTR)md->start_subject; |
| cb.subject_length = md->end_subject - md->start_subject; | cb.subject_length = (int)(md->end_subject - md->start_subject); |
| cb.start_match = mstart - md->start_subject; | cb.start_match = (int)(mstart - md->start_subject); |
| cb.current_position = eptr - md->start_subject; | cb.current_position = (int)(eptr - md->start_subject); |
| cb.pattern_position = GET(ecode, 2); | cb.pattern_position = GET(ecode, 2); |
| cb.next_item_length = GET(ecode, 2 + LINK_SIZE); | cb.next_item_length = GET(ecode, 2 + LINK_SIZE); |
| cb.capture_top = offset_top/2; | cb.capture_top = offset_top/2; |
| cb.capture_last = md->capture_last; | cb.capture_last = md->capture_last; |
| cb.callout_data = md->callout_data; | cb.callout_data = md->callout_data; |
| if ((rrc = (*pcre_callout)(&cb)) > 0) RRETURN(MATCH_NOMATCH); | if ((rrc = (*pcre_callout)(&cb)) > 0) MRRETURN(MATCH_NOMATCH); |
| if (rrc < 0) RRETURN(rrc); | if (rrc < 0) RRETURN(rrc); |
| } | } |
| ecode += 2 + 2*LINK_SIZE; | ecode += 2 + 2*LINK_SIZE; |
| Line 1052 for (;;) | Line 1374 for (;;) |
| memcpy(new_recursive.offset_save, md->offset_vector, | memcpy(new_recursive.offset_save, md->offset_vector, |
| new_recursive.saved_max * sizeof(int)); | new_recursive.saved_max * sizeof(int)); |
| new_recursive.save_start = mstart; | new_recursive.save_offset_top = offset_top; |
| mstart = eptr; | |
| /* 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 |
| restore the offset and recursion data. */ | restore the offset and recursion data. */ |
| Line 1064 for (;;) | Line 1385 for (;;) |
| { | { |
| RMATCH(eptr, callpat + _pcre_OP_lengths[*callpat], offset_top, | RMATCH(eptr, callpat + _pcre_OP_lengths[*callpat], offset_top, |
| md, ims, eptrb, flags, RM6); | md, ims, eptrb, flags, RM6); |
| if (rrc == MATCH_MATCH) | if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) |
| { | { |
| DPRINTF(("Recursion matched\n")); | DPRINTF(("Recursion matched\n")); |
| md->recursive = new_recursive.prevrec; | md->recursive = new_recursive.prevrec; |
| if (new_recursive.offset_save != stacksave) | if (new_recursive.offset_save != stacksave) |
| (pcre_free)(new_recursive.offset_save); | (pcre_free)(new_recursive.offset_save); |
| RRETURN(MATCH_MATCH); | MRRETURN(MATCH_MATCH); |
| } | } |
| else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) | else if (rrc != MATCH_NOMATCH && |
| (rrc != MATCH_THEN || md->start_match_ptr != ecode)) | |
| { | { |
| DPRINTF(("Recursion gave error %d\n", rrc)); | DPRINTF(("Recursion gave error %d\n", rrc)); |
| if (new_recursive.offset_save != stacksave) | |
| (pcre_free)(new_recursive.offset_save); | |
| RRETURN(rrc); | RRETURN(rrc); |
| } | } |
| Line 1089 for (;;) | Line 1413 for (;;) |
| md->recursive = new_recursive.prevrec; | md->recursive = new_recursive.prevrec; |
| if (new_recursive.offset_save != stacksave) | if (new_recursive.offset_save != stacksave) |
| (pcre_free)(new_recursive.offset_save); | (pcre_free)(new_recursive.offset_save); |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| /* Control never reaches here */ | /* Control never reaches here */ |
| Line 1098 for (;;) | Line 1422 for (;;) |
| a move back into the brackets. Friedl calls these "atomic" subpatterns. | a move back into the brackets. Friedl calls these "atomic" subpatterns. |
| Check the alternative branches in turn - the matching won't pass the KET | Check the alternative branches in turn - the matching won't pass the KET |
| for this kind of subpattern. If any one branch matches, we carry on as at | for this kind of subpattern. If any one branch matches, we carry on as at |
| the end of a normal bracket, leaving the subject pointer. */ | the end of a normal bracket, leaving the subject pointer, but resetting |
| the start-of-match value in case it was changed by \K. */ | |
| case OP_ONCE: | case OP_ONCE: |
| prev = ecode; | prev = ecode; |
| Line 1107 for (;;) | Line 1432 for (;;) |
| do | do |
| { | { |
| RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM7); | RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM7); |
| if (rrc == MATCH_MATCH) break; | if (rrc == MATCH_MATCH) /* Note: _not_ MATCH_ACCEPT */ |
| if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); | { |
| mstart = md->start_match_ptr; | |
| break; | |
| } | |
| if (rrc != MATCH_NOMATCH && | |
| (rrc != MATCH_THEN || md->start_match_ptr != ecode)) | |
| RRETURN(rrc); | |
| ecode += GET(ecode,1); | ecode += GET(ecode,1); |
| } | } |
| while (*ecode == OP_ALT); | while (*ecode == OP_ALT); |
| Line 1226 for (;;) | Line 1557 for (;;) |
| } | } |
| else saved_eptr = NULL; | else saved_eptr = NULL; |
| /* If we are at the end of an assertion group, stop matching and return | /* If we are at the end of an assertion group or an atomic group, stop |
| MATCH_MATCH, but record the current high water mark for use by positive | matching and return MATCH_MATCH, but record the current high water mark for |
| assertions. Do this also for the "once" (atomic) groups. */ | use by positive assertions. We also need to record the match start in case |
| it was changed by \K. */ | |
| if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT || | if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT || |
| *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT || | *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT || |
| Line 1236 for (;;) | Line 1568 for (;;) |
| { | { |
| md->end_match_ptr = eptr; /* For ONCE */ | md->end_match_ptr = eptr; /* For ONCE */ |
| md->end_offset_top = offset_top; | md->end_offset_top = offset_top; |
| RRETURN(MATCH_MATCH); | md->start_match_ptr = mstart; |
| MRRETURN(MATCH_MATCH); | |
| } | } |
| /* For capturing groups we have to check the group number back at the start | /* For capturing groups we have to check the group number back at the start |
| Line 1250 for (;;) | Line 1583 for (;;) |
| number = GET2(prev, 1+LINK_SIZE); | number = GET2(prev, 1+LINK_SIZE); |
| offset = number << 1; | offset = number << 1; |
| #ifdef DEBUG | #ifdef PCRE_DEBUG |
| printf("end bracket %d", number); | printf("end bracket %d", number); |
| printf("\n"); | printf("\n"); |
| #endif | #endif |
| Line 1260 for (;;) | Line 1593 for (;;) |
| { | { |
| md->offset_vector[offset] = | md->offset_vector[offset] = |
| md->offset_vector[md->offset_end - number]; | md->offset_vector[md->offset_end - number]; |
| md->offset_vector[offset+1] = eptr - md->start_subject; | md->offset_vector[offset+1] = (int)(eptr - md->start_subject); |
| if (offset_top <= offset) offset_top = offset + 2; | if (offset_top <= offset) offset_top = offset + 2; |
| } | } |
| Line 1272 for (;;) | Line 1605 for (;;) |
| recursion_info *rec = md->recursive; | recursion_info *rec = md->recursive; |
| DPRINTF(("Recursion (%d) succeeded - continuing\n", number)); | DPRINTF(("Recursion (%d) succeeded - continuing\n", number)); |
| md->recursive = rec->prevrec; | md->recursive = rec->prevrec; |
| mstart = rec->save_start; | |
| memcpy(md->offset_vector, rec->offset_save, | memcpy(md->offset_vector, rec->offset_save, |
| rec->saved_max * sizeof(int)); | rec->saved_max * sizeof(int)); |
| offset_top = rec->save_offset_top; | |
| ecode = rec->after_call; | ecode = rec->after_call; |
| ims = original_ims; | ims = original_ims; |
| break; | break; |
| Line 1331 for (;;) | Line 1664 for (;;) |
| /* Start of subject unless notbol, or after internal newline if multiline */ | /* Start of subject unless notbol, or after internal newline if multiline */ |
| case OP_CIRC: | case OP_CIRC: |
| if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH); | if (md->notbol && eptr == md->start_subject) MRRETURN(MATCH_NOMATCH); |
| if ((ims & PCRE_MULTILINE) != 0) | if ((ims & PCRE_MULTILINE) != 0) |
| { | { |
| if (eptr != md->start_subject && | if (eptr != md->start_subject && |
| (eptr == md->end_subject || !WAS_NEWLINE(eptr))) | (eptr == md->end_subject || !WAS_NEWLINE(eptr))) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| ecode++; | ecode++; |
| break; | break; |
| } | } |
| Line 1345 for (;;) | Line 1678 for (;;) |
| /* Start of subject assertion */ | /* Start of subject assertion */ |
| case OP_SOD: | case OP_SOD: |
| if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH); | if (eptr != md->start_subject) MRRETURN(MATCH_NOMATCH); |
| ecode++; | ecode++; |
| break; | break; |
| /* Start of match assertion */ | /* Start of match assertion */ |
| case OP_SOM: | case OP_SOM: |
| if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH); | if (eptr != md->start_subject + md->start_offset) MRRETURN(MATCH_NOMATCH); |
| ecode++; | ecode++; |
| break; | break; |
| Line 1370 for (;;) | Line 1703 for (;;) |
| if ((ims & PCRE_MULTILINE) != 0) | if ((ims & PCRE_MULTILINE) != 0) |
| { | { |
| if (eptr < md->end_subject) | if (eptr < md->end_subject) |
| { if (!IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); } | { if (!IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); } |
| else | else |
| { if (md->noteol) RRETURN(MATCH_NOMATCH); } | { |
| if (md->noteol) MRRETURN(MATCH_NOMATCH); | |
| SCHECK_PARTIAL(); | |
| } | |
| ecode++; | ecode++; |
| break; | break; |
| } | } |
| else | else /* Not multiline */ |
| { | { |
| if (md->noteol) RRETURN(MATCH_NOMATCH); | if (md->noteol) MRRETURN(MATCH_NOMATCH); |
| if (!md->endonly) | if (!md->endonly) goto ASSERT_NL_OR_EOS; |
| { | |
| if (eptr != md->end_subject && | |
| (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen)) | |
| RRETURN(MATCH_NOMATCH); | |
| ecode++; | |
| break; | |
| } | |
| } | } |
| /* ... else fall through for endonly */ | /* ... else fall through for endonly */ |
| /* End of subject assertion (\z) */ | /* End of subject assertion (\z) */ |
| case OP_EOD: | case OP_EOD: |
| if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr < md->end_subject) MRRETURN(MATCH_NOMATCH); |
| SCHECK_PARTIAL(); | |
| ecode++; | ecode++; |
| break; | break; |
| /* End of subject or ending \n assertion (\Z) */ | /* End of subject or ending \n assertion (\Z) */ |
| case OP_EODN: | case OP_EODN: |
| if (eptr != md->end_subject && | ASSERT_NL_OR_EOS: |
| if (eptr < md->end_subject && | |
| (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen)) | (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen)) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| /* Either at end of string or \n before end. */ | |
| SCHECK_PARTIAL(); | |
| ecode++; | ecode++; |
| break; | break; |
| Line 1414 for (;;) | Line 1750 for (;;) |
| /* Find out if the previous and current characters are "word" characters. | /* Find out if the previous and current characters are "word" characters. |
| 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 |
| be "non-word" characters. */ | be "non-word" characters. Remember the earliest consulted character for |
| partial matching. */ | |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| if (utf8) | if (utf8) |
| { | { |
| /* Get status of previous character */ | |
| if (eptr == md->start_subject) prev_is_word = FALSE; else | if (eptr == md->start_subject) prev_is_word = FALSE; else |
| { | { |
| const uschar *lastptr = eptr - 1; | USPTR lastptr = eptr - 1; |
| while((*lastptr & 0xc0) == 0x80) lastptr--; | while((*lastptr & 0xc0) == 0x80) lastptr--; |
| if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr; | |
| GETCHAR(c, lastptr); | GETCHAR(c, lastptr); |
| #ifdef SUPPORT_UCP | |
| if (md->use_ucp) | |
| { | |
| if (c == '_') prev_is_word = TRUE; else | |
| { | |
| int cat = UCD_CATEGORY(c); | |
| prev_is_word = (cat == ucp_L || cat == ucp_N); | |
| } | |
| } | |
| else | |
| #endif | |
| prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; | prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; |
| } | } |
| if (eptr >= md->end_subject) cur_is_word = FALSE; else | |
| /* Get status of next character */ | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| cur_is_word = FALSE; | |
| } | |
| else | |
| { | { |
| GETCHAR(c, eptr); | GETCHAR(c, eptr); |
| #ifdef SUPPORT_UCP | |
| if (md->use_ucp) | |
| { | |
| if (c == '_') cur_is_word = TRUE; else | |
| { | |
| int cat = UCD_CATEGORY(c); | |
| cur_is_word = (cat == ucp_L || cat == ucp_N); | |
| } | |
| } | |
| else | |
| #endif | |
| cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; | cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; |
| } | } |
| } | } |
| else | else |
| #endif | #endif |
| /* More streamlined when not in UTF-8 mode */ | /* Not in UTF-8 mode, but we may still have PCRE_UCP set, and for |
| consistency with the behaviour of \w we do use it in this case. */ | |
| { | { |
| prev_is_word = (eptr != md->start_subject) && | /* Get status of previous character */ |
| ((md->ctypes[eptr[-1]] & ctype_word) != 0); | |
| cur_is_word = (eptr < md->end_subject) && | if (eptr == md->start_subject) prev_is_word = FALSE; else |
| ((md->ctypes[*eptr] & ctype_word) != 0); | { |
| if (eptr <= md->start_used_ptr) md->start_used_ptr = eptr - 1; | |
| #ifdef SUPPORT_UCP | |
| if (md->use_ucp) | |
| { | |
| c = eptr[-1]; | |
| if (c == '_') prev_is_word = TRUE; else | |
| { | |
| int cat = UCD_CATEGORY(c); | |
| prev_is_word = (cat == ucp_L || cat == ucp_N); | |
| } | |
| } | |
| else | |
| #endif | |
| prev_is_word = ((md->ctypes[eptr[-1]] & ctype_word) != 0); | |
| } | |
| /* Get status of next character */ | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| cur_is_word = FALSE; | |
| } | |
| else | |
| #ifdef SUPPORT_UCP | |
| if (md->use_ucp) | |
| { | |
| c = *eptr; | |
| if (c == '_') cur_is_word = TRUE; else | |
| { | |
| int cat = UCD_CATEGORY(c); | |
| cur_is_word = (cat == ucp_L || cat == ucp_N); | |
| } | |
| } | |
| else | |
| #endif | |
| cur_is_word = ((md->ctypes[*eptr] & ctype_word) != 0); | |
| } | } |
| /* Now see if the situation is what we want */ | /* Now see if the situation is what we want */ |
| if ((*ecode++ == OP_WORD_BOUNDARY)? | if ((*ecode++ == OP_WORD_BOUNDARY)? |
| cur_is_word == prev_is_word : cur_is_word != prev_is_word) | cur_is_word == prev_is_word : cur_is_word != prev_is_word) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| break; | break; |
| /* Match a single character type; inline for speed */ | /* Match a single character type; inline for speed */ |
| case OP_ANY: | case OP_ANY: |
| if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); | if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); |
| /* Fall through */ | /* Fall through */ |
| case OP_ALLANY: | case OP_ALLANY: |
| if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr++ >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; | if (utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; |
| ecode++; | ecode++; |
| break; | break; |
| Line 1468 for (;;) | Line 1880 for (;;) |
| any byte, even newline, independent of the setting of PCRE_DOTALL. */ | any byte, even newline, independent of the setting of PCRE_DOTALL. */ |
| case OP_ANYBYTE: | case OP_ANYBYTE: |
| if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr++ >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| ecode++; | ecode++; |
| break; | break; |
| case OP_NOT_DIGIT: | case OP_NOT_DIGIT: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| if ( | if ( |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| Line 1481 for (;;) | Line 1901 for (;;) |
| #endif | #endif |
| (md->ctypes[c] & ctype_digit) != 0 | (md->ctypes[c] & ctype_digit) != 0 |
| ) | ) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| ecode++; | ecode++; |
| break; | break; |
| case OP_DIGIT: | case OP_DIGIT: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| if ( | if ( |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| Line 1494 for (;;) | Line 1918 for (;;) |
| #endif | #endif |
| (md->ctypes[c] & ctype_digit) == 0 | (md->ctypes[c] & ctype_digit) == 0 |
| ) | ) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| ecode++; | ecode++; |
| break; | break; |
| case OP_NOT_WHITESPACE: | case OP_NOT_WHITESPACE: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| if ( | if ( |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| Line 1507 for (;;) | Line 1935 for (;;) |
| #endif | #endif |
| (md->ctypes[c] & ctype_space) != 0 | (md->ctypes[c] & ctype_space) != 0 |
| ) | ) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| ecode++; | ecode++; |
| break; | break; |
| case OP_WHITESPACE: | case OP_WHITESPACE: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| if ( | if ( |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| Line 1520 for (;;) | Line 1952 for (;;) |
| #endif | #endif |
| (md->ctypes[c] & ctype_space) == 0 | (md->ctypes[c] & ctype_space) == 0 |
| ) | ) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| ecode++; | ecode++; |
| break; | break; |
| case OP_NOT_WORDCHAR: | case OP_NOT_WORDCHAR: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| if ( | if ( |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| Line 1533 for (;;) | Line 1969 for (;;) |
| #endif | #endif |
| (md->ctypes[c] & ctype_word) != 0 | (md->ctypes[c] & ctype_word) != 0 |
| ) | ) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| ecode++; | ecode++; |
| break; | break; |
| case OP_WORDCHAR: | case OP_WORDCHAR: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| if ( | if ( |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| Line 1546 for (;;) | Line 1986 for (;;) |
| #endif | #endif |
| (md->ctypes[c] & ctype_word) == 0 | (md->ctypes[c] & ctype_word) == 0 |
| ) | ) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| ecode++; | ecode++; |
| break; | break; |
| case OP_ANYNL: | case OP_ANYNL: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x000d: | case 0x000d: |
| if (eptr < md->end_subject && *eptr == 0x0a) eptr++; | if (eptr < md->end_subject && *eptr == 0x0a) eptr++; |
| break; | break; |
| Line 1568 for (;;) | Line 2012 for (;;) |
| case 0x0085: | case 0x0085: |
| case 0x2028: | case 0x2028: |
| case 0x2029: | case 0x2029: |
| if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); | if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| } | } |
| ecode++; | ecode++; |
| break; | break; |
| case OP_NOT_HSPACE: | case OP_NOT_HSPACE: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| switch(c) | switch(c) |
| { | { |
| Line 1599 for (;;) | Line 2047 for (;;) |
| case 0x202f: /* NARROW NO-BREAK SPACE */ | case 0x202f: /* NARROW NO-BREAK SPACE */ |
| case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ | case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ |
| case 0x3000: /* IDEOGRAPHIC SPACE */ | case 0x3000: /* IDEOGRAPHIC SPACE */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| ecode++; | ecode++; |
| break; | break; |
| case OP_HSPACE: | case OP_HSPACE: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x09: /* HT */ | case 0x09: /* HT */ |
| case 0x20: /* SPACE */ | case 0x20: /* SPACE */ |
| case 0xa0: /* NBSP */ | case 0xa0: /* NBSP */ |
| Line 1635 for (;;) | Line 2087 for (;;) |
| break; | break; |
| case OP_NOT_VSPACE: | case OP_NOT_VSPACE: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| switch(c) | switch(c) |
| { | { |
| Line 1647 for (;;) | Line 2103 for (;;) |
| case 0x85: /* NEL */ | case 0x85: /* NEL */ |
| case 0x2028: /* LINE SEPARATOR */ | case 0x2028: /* LINE SEPARATOR */ |
| case 0x2029: /* PARAGRAPH SEPARATOR */ | case 0x2029: /* PARAGRAPH SEPARATOR */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| ecode++; | ecode++; |
| break; | break; |
| case OP_VSPACE: | case OP_VSPACE: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x0a: /* LF */ | case 0x0a: /* LF */ |
| case 0x0b: /* VT */ | case 0x0b: /* VT */ |
| case 0x0c: /* FF */ | case 0x0c: /* FF */ |
| Line 1676 for (;;) | Line 2136 for (;;) |
| case OP_PROP: | case OP_PROP: |
| case OP_NOTPROP: | case OP_NOTPROP: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| { | { |
| const ucd_record * prop = GET_UCD(c); | const ucd_record *prop = GET_UCD(c); |
| switch(ecode[1]) | switch(ecode[1]) |
| { | { |
| case PT_ANY: | case PT_ANY: |
| if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH); | if (op == OP_NOTPROP) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case PT_LAMP: | case PT_LAMP: |
| if ((prop->chartype == ucp_Lu || | if ((prop->chartype == ucp_Lu || |
| prop->chartype == ucp_Ll || | prop->chartype == ucp_Ll || |
| prop->chartype == ucp_Lt) == (op == OP_NOTPROP)) | prop->chartype == ucp_Lt) == (op == OP_NOTPROP)) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case PT_GC: | case PT_GC: |
| if ((ecode[2] != _pcre_ucp_gentype[prop->chartype]) == (op == OP_PROP)) | if ((ecode[2] != _pcre_ucp_gentype[prop->chartype]) == (op == OP_PROP)) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case PT_PC: | case PT_PC: |
| if ((ecode[2] != prop->chartype) == (op == OP_PROP)) | if ((ecode[2] != prop->chartype) == (op == OP_PROP)) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case PT_SC: | case PT_SC: |
| if ((ecode[2] != prop->script) == (op == OP_PROP)) | if ((ecode[2] != prop->script) == (op == OP_PROP)) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| break; | |
| /* These are specials */ | |
| case PT_ALNUM: | |
| if ((_pcre_ucp_gentype[prop->chartype] == ucp_L || | |
| _pcre_ucp_gentype[prop->chartype] == ucp_N) == (op == OP_NOTPROP)) | |
| MRRETURN(MATCH_NOMATCH); | |
| break; | |
| case PT_SPACE: /* Perl space */ | |
| if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z || | |
| c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) | |
| == (op == OP_NOTPROP)) | |
| MRRETURN(MATCH_NOMATCH); | |
| break; | break; |
| case PT_PXSPACE: /* POSIX space */ | |
| if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z || | |
| c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || | |
| c == CHAR_FF || c == CHAR_CR) | |
| == (op == OP_NOTPROP)) | |
| MRRETURN(MATCH_NOMATCH); | |
| break; | |
| case PT_WORD: | |
| if ((_pcre_ucp_gentype[prop->chartype] == ucp_L || | |
| _pcre_ucp_gentype[prop->chartype] == ucp_N || | |
| c == CHAR_UNDERSCORE) == (op == OP_NOTPROP)) | |
| MRRETURN(MATCH_NOMATCH); | |
| break; | |
| /* This should never occur */ | |
| default: | default: |
| RRETURN(PCRE_ERROR_INTERNAL); | RRETURN(PCRE_ERROR_INTERNAL); |
| } | } |
| Line 1721 for (;;) | Line 2217 for (;;) |
| is in the binary; otherwise a compile-time error occurs. */ | is in the binary; otherwise a compile-time error occurs. */ |
| case OP_EXTUNI: | case OP_EXTUNI: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| { | { |
| int category = UCD_CATEGORY(c); | int category = UCD_CATEGORY(c); |
| if (category == ucp_M) RRETURN(MATCH_NOMATCH); | if (category == ucp_M) MRRETURN(MATCH_NOMATCH); |
| while (eptr < md->end_subject) | while (eptr < md->end_subject) |
| { | { |
| int len = 1; | int len = 1; |
| Line 1770 for (;;) | Line 2270 for (;;) |
| referenced subpattern. */ | referenced subpattern. */ |
| if (offset >= offset_top || md->offset_vector[offset] < 0) | if (offset >= offset_top || md->offset_vector[offset] < 0) |
| length = (md->jscript_compat)? 0 : md->end_subject - eptr + 1; | length = (md->jscript_compat)? 0 : (int)(md->end_subject - eptr + 1); |
| else | else |
| length = md->offset_vector[offset+1] - md->offset_vector[offset]; | length = md->offset_vector[offset+1] - md->offset_vector[offset]; |
| Line 1801 for (;;) | Line 2301 for (;;) |
| break; | break; |
| default: /* No repeat follows */ | default: /* No repeat follows */ |
| if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH); | if (!match_ref(offset, eptr, length, md, ims)) |
| { | |
| CHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| eptr += length; | eptr += length; |
| continue; /* With the main loop */ | continue; /* With the main loop */ |
| } | } |
| Line 1817 for (;;) | Line 2321 for (;;) |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH); | if (!match_ref(offset, eptr, length, md, ims)) |
| { | |
| CHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| eptr += length; | eptr += length; |
| } | } |
| Line 1834 for (;;) | Line 2342 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || !match_ref(offset, eptr, length, md, ims)) | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| RRETURN(MATCH_NOMATCH); | if (!match_ref(offset, eptr, length, md, ims)) |
| { | |
| CHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| eptr += length; | eptr += length; |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 1848 for (;;) | Line 2360 for (;;) |
| pp = eptr; | pp = eptr; |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (!match_ref(offset, eptr, length, md, ims)) break; | if (!match_ref(offset, eptr, length, md, ims)) |
| { | |
| CHECK_PARTIAL(); | |
| break; | |
| } | |
| eptr += length; | eptr += length; |
| } | } |
| while (eptr >= pp) | while (eptr >= pp) |
| Line 1857 for (;;) | Line 2373 for (;;) |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| eptr -= length; | eptr -= length; |
| } | } |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| /* Match a bit-mapped character class, possibly repeatedly. This op code is | /* Match a bit-mapped character class, possibly repeatedly. This op code is |
| 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, |
| 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 1918 for (;;) | Line 2432 for (;;) |
| { | { |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(c, eptr); | GETCHARINC(c, eptr); |
| if (c > 255) | if (c > 255) |
| { | { |
| if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); | if (op == OP_CLASS) MRRETURN(MATCH_NOMATCH); |
| } | } |
| else | else |
| { | { |
| if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); | if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| } | } |
| Line 1936 for (;;) | Line 2454 for (;;) |
| { | { |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| c = *eptr++; | c = *eptr++; |
| if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); | if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| Line 1960 for (;;) | Line 2482 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(c, eptr); | GETCHARINC(c, eptr); |
| if (c > 255) | if (c > 255) |
| { | { |
| if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); | if (op == OP_CLASS) MRRETURN(MATCH_NOMATCH); |
| } | } |
| else | else |
| { | { |
| if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); | if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| } | } |
| Line 1980 for (;;) | Line 2507 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| c = *eptr++; | c = *eptr++; |
| if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); | if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 2001 for (;;) | Line 2533 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(c, eptr, len); | GETCHARLEN(c, eptr, len); |
| if (c > 255) | if (c > 255) |
| { | { |
| Line 2027 for (;;) | Line 2563 for (;;) |
| { | { |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| c = *eptr; | c = *eptr; |
| if ((data[c/8] & (1 << (c&7))) == 0) break; | if ((data[c/8] & (1 << (c&7))) == 0) break; |
| eptr++; | eptr++; |
| Line 2040 for (;;) | Line 2580 for (;;) |
| } | } |
| } | } |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| /* Match an extended character class. This opcode is encountered only | /* Match an extended character class. This opcode is encountered only |
| in UTF-8 mode, because that's the only time it is compiled. */ | when UTF-8 mode mode is supported. Nevertheless, we may not be in UTF-8 |
| mode, because Unicode properties are supported in non-UTF-8 mode. */ | |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| case OP_XCLASS: | case OP_XCLASS: |
| Line 2088 for (;;) | Line 2629 for (;;) |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| GETCHARINC(c, eptr); | { |
| if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH); | SCHECK_PARTIAL(); |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| if (!_pcre_xclass(c, data)) MRRETURN(MATCH_NOMATCH); | |
| } | } |
| /* If max == min we can continue with the main loop without the | /* If max == min we can continue with the main loop without the |
| Line 2107 for (;;) | Line 2652 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| GETCHARINC(c, eptr); | if (eptr >= md->end_subject) |
| if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH); | { |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| if (!_pcre_xclass(c, data)) MRRETURN(MATCH_NOMATCH); | |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| } | } |
| Line 2122 for (;;) | Line 2672 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| GETCHARLEN(c, eptr, len); | { |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLENTEST(c, eptr, len); | |
| if (!_pcre_xclass(c, data)) break; | if (!_pcre_xclass(c, data)) break; |
| eptr += len; | eptr += len; |
| } | } |
| Line 2134 for (;;) | Line 2688 for (;;) |
| if (eptr-- == pp) break; /* Stop if tried at original pos */ | if (eptr-- == pp) break; /* Stop if tried at original pos */ |
| if (utf8) BACKCHAR(eptr); | if (utf8) BACKCHAR(eptr); |
| } | } |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 2150 for (;;) | Line 2704 for (;;) |
| length = 1; | length = 1; |
| ecode++; | ecode++; |
| GETCHARLEN(fc, ecode, length); | GETCHARLEN(fc, ecode, length); |
| if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); | if (length > md->end_subject - eptr) |
| while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH); | { |
| CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */ | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| while (length-- > 0) if (*ecode++ != *eptr++) MRRETURN(MATCH_NOMATCH); | |
| } | } |
| else | else |
| #endif | #endif |
| /* Non-UTF-8 mode */ | /* Non-UTF-8 mode */ |
| { | { |
| if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH); | if (md->end_subject - eptr < 1) |
| if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH); | { |
| SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */ | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (ecode[1] != *eptr++) MRRETURN(MATCH_NOMATCH); | |
| ecode += 2; | ecode += 2; |
| } | } |
| break; | break; |
| Line 2174 for (;;) | Line 2736 for (;;) |
| ecode++; | ecode++; |
| GETCHARLEN(fc, ecode, length); | GETCHARLEN(fc, ecode, length); |
| if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); | if (length > md->end_subject - eptr) |
| { | |
| CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */ | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| /* 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 |
| can use the fast lookup table. */ | can use the fast lookup table. */ |
| if (fc < 128) | if (fc < 128) |
| { | { |
| if (md->lcc[*ecode++] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); | if (md->lcc[*ecode++] != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); |
| } | } |
| /* Otherwise we must pick up the subject character */ | /* Otherwise we must pick up the subject character */ |
| Line 2200 for (;;) | Line 2766 for (;;) |
| #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
| if (dc != UCD_OTHERCASE(fc)) | if (dc != UCD_OTHERCASE(fc)) |
| #endif | #endif |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| } | } |
| Line 2209 for (;;) | Line 2775 for (;;) |
| /* Non-UTF-8 mode */ | /* Non-UTF-8 mode */ |
| { | { |
| if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH); | if (md->end_subject - eptr < 1) |
| if (md->lcc[ecode[1]] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); | { |
| SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */ | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (md->lcc[ecode[1]] != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); | |
| ecode += 2; | ecode += 2; |
| } | } |
| break; | break; |
| Line 2263 for (;;) | Line 2833 for (;;) |
| case OP_MINQUERY: | case OP_MINQUERY: |
| c = *ecode++ - OP_STAR; | c = *ecode++ - OP_STAR; |
| minimize = (c & 1) != 0; | minimize = (c & 1) != 0; |
| min = rep_min[c]; /* Pick up values from tables; */ | min = rep_min[c]; /* Pick up values from tables; */ |
| max = rep_max[c]; /* zero for max => infinity */ | max = rep_max[c]; /* zero for max => infinity */ |
| if (max == 0) max = INT_MAX; | if (max == 0) max = INT_MAX; |
| /* 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. */ | |
| REPEATCHAR: | REPEATCHAR: |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| Line 2278 for (;;) | Line 2847 for (;;) |
| length = 1; | length = 1; |
| charptr = ecode; | charptr = ecode; |
| GETCHARLEN(fc, ecode, length); | GETCHARLEN(fc, ecode, length); |
| if (min * length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); | |
| ecode += length; | ecode += length; |
| /* Handle multibyte character matching specially here. There is | /* Handle multibyte character matching specially here. There is |
| Line 2296 for (;;) | Line 2864 for (;;) |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (memcmp(eptr, charptr, length) == 0) eptr += length; | if (eptr <= md->end_subject - length && |
| memcmp(eptr, charptr, length) == 0) eptr += length; | |
| #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
| /* Need braces because of following else */ | else if (oclength > 0 && |
| else if (oclength == 0) { RRETURN(MATCH_NOMATCH); } | eptr <= md->end_subject - oclength && |
| memcmp(eptr, occhars, oclength) == 0) eptr += oclength; | |
| #endif /* SUPPORT_UCP */ | |
| else | else |
| { | { |
| if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH); | CHECK_PARTIAL(); |
| eptr += oclength; | MRRETURN(MATCH_NOMATCH); |
| } | } |
| #else /* without SUPPORT_UCP */ | |
| else { RRETURN(MATCH_NOMATCH); } | |
| #endif /* SUPPORT_UCP */ | |
| } | } |
| if (min == max) continue; | if (min == max) continue; |
| Line 2318 for (;;) | Line 2886 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| if (memcmp(eptr, charptr, length) == 0) eptr += length; | if (eptr <= md->end_subject - length && |
| memcmp(eptr, charptr, length) == 0) eptr += length; | |
| #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
| /* Need braces because of following else */ | else if (oclength > 0 && |
| else if (oclength == 0) { RRETURN(MATCH_NOMATCH); } | eptr <= md->end_subject - oclength && |
| memcmp(eptr, occhars, oclength) == 0) eptr += oclength; | |
| #endif /* SUPPORT_UCP */ | |
| else | else |
| { | { |
| if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH); | CHECK_PARTIAL(); |
| eptr += oclength; | MRRETURN(MATCH_NOMATCH); |
| } | } |
| #else /* without SUPPORT_UCP */ | |
| else { RRETURN (MATCH_NOMATCH); } | |
| #endif /* SUPPORT_UCP */ | |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| } | } |
| Line 2340 for (;;) | Line 2908 for (;;) |
| pp = eptr; | pp = eptr; |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr > md->end_subject - length) break; | if (eptr <= md->end_subject - length && |
| if (memcmp(eptr, charptr, length) == 0) eptr += length; | memcmp(eptr, charptr, length) == 0) eptr += length; |
| #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
| else if (oclength == 0) break; | else if (oclength > 0 && |
| eptr <= md->end_subject - oclength && | |
| memcmp(eptr, occhars, oclength) == 0) eptr += oclength; | |
| #endif /* SUPPORT_UCP */ | |
| else | else |
| { | { |
| if (memcmp(eptr, occhars, oclength) != 0) break; | CHECK_PARTIAL(); |
| eptr += oclength; | break; |
| } | } |
| #else /* without SUPPORT_UCP */ | |
| else break; | |
| #endif /* SUPPORT_UCP */ | |
| } | } |
| if (possessive) continue; | if (possessive) continue; |
| for(;;) | for(;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (eptr == pp) RRETURN(MATCH_NOMATCH); | if (eptr == pp) { MRRETURN(MATCH_NOMATCH); } |
| #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
| eptr--; | eptr--; |
| BACKCHAR(eptr); | BACKCHAR(eptr); |
| #else /* without SUPPORT_UCP */ | #else /* without SUPPORT_UCP */ |
| eptr -= length; | eptr -= length; |
| #endif /* SUPPORT_UCP */ | #endif /* SUPPORT_UCP */ |
| } | } |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| } | } |
| Line 2379 for (;;) | Line 2948 for (;;) |
| #endif /* SUPPORT_UTF8 */ | #endif /* SUPPORT_UTF8 */ |
| /* When not in UTF-8 mode, load a single-byte character. */ | /* When not in UTF-8 mode, load a single-byte character. */ |
| { | |
| if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); | fc = *ecode++; |
| fc = *ecode++; | |
| } | |
| /* 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 |
| 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 2400 for (;;) | Line 2967 for (;;) |
| { | { |
| fc = md->lcc[fc]; | fc = md->lcc[fc]; |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); | { |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (fc != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (min == max) continue; | if (min == max) continue; |
| if (minimize) | if (minimize) |
| { | { |
| Line 2408 for (;;) | Line 2982 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject || | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| fc != md->lcc[*eptr++]) | if (eptr >= md->end_subject) |
| RRETURN(MATCH_NOMATCH); | { |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (fc != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); | |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| } | } |
| Line 2419 for (;;) | Line 2997 for (;;) |
| pp = eptr; | pp = eptr; |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || fc != md->lcc[*eptr]) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| if (fc != md->lcc[*eptr]) break; | |
| eptr++; | eptr++; |
| } | } |
| if (possessive) continue; | if (possessive) continue; |
| while (eptr >= pp) | while (eptr >= pp) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25); |
| eptr--; | eptr--; |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| } | } |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| } | } |
| Line 2438 for (;;) | Line 3023 for (;;) |
| else | else |
| { | { |
| for (i = 1; i <= min; i++) if (fc != *eptr++) RRETURN(MATCH_NOMATCH); | for (i = 1; i <= min; i++) |
| { | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (fc != *eptr++) MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (min == max) continue; | if (min == max) continue; |
| if (minimize) | if (minimize) |
| { | { |
| for (fi = min;; fi++) | for (fi = min;; fi++) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject || fc != *eptr++) | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (fc != *eptr++) MRRETURN(MATCH_NOMATCH); | |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| } | } |
| Line 2456 for (;;) | Line 3056 for (;;) |
| pp = eptr; | pp = eptr; |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || fc != *eptr) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| if (fc != *eptr) break; | |
| eptr++; | eptr++; |
| } | } |
| if (possessive) continue; | if (possessive) continue; |
| while (eptr >= pp) | while (eptr >= pp) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM27); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM27); |
| eptr--; | eptr--; |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| } | } |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 2475 for (;;) | Line 3081 for (;;) |
| checking can be multibyte. */ | checking can be multibyte. */ |
| case OP_NOT: | case OP_NOT: |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| ecode++; | ecode++; |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| if ((ims & PCRE_CASELESS) != 0) | if ((ims & PCRE_CASELESS) != 0) |
| Line 2484 for (;;) | Line 3094 for (;;) |
| if (c < 256) | if (c < 256) |
| #endif | #endif |
| c = md->lcc[c]; | c = md->lcc[c]; |
| if (md->lcc[*ecode++] == c) RRETURN(MATCH_NOMATCH); | if (md->lcc[*ecode++] == c) MRRETURN(MATCH_NOMATCH); |
| } | } |
| else | else |
| { | { |
| if (*ecode++ == c) RRETURN(MATCH_NOMATCH); | if (*ecode++ == c) MRRETURN(MATCH_NOMATCH); |
| } | } |
| break; | break; |
| Line 2552 for (;;) | Line 3162 for (;;) |
| max = rep_max[c]; /* zero for max => infinity */ | max = rep_max[c]; /* zero for max => infinity */ |
| if (max == 0) max = INT_MAX; | if (max == 0) max = INT_MAX; |
| /* 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. */ | |
| REPEATNOTCHAR: | REPEATNOTCHAR: |
| if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); | |
| fc = *ecode++; | fc = *ecode++; |
| /* 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 2582 for (;;) | Line 3189 for (;;) |
| register unsigned int d; | register unsigned int d; |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(d, eptr); | GETCHARINC(d, eptr); |
| if (d < 256) d = md->lcc[d]; | if (d < 256) d = md->lcc[d]; |
| if (fc == d) RRETURN(MATCH_NOMATCH); | if (fc == d) MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| else | else |
| Line 2593 for (;;) | Line 3205 for (;;) |
| /* Not UTF-8 mode */ | /* Not UTF-8 mode */ |
| { | { |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); | { |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (fc == md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); | |
| } | |
| } | } |
| if (min == max) continue; | if (min == max) continue; |
| Line 2609 for (;;) | Line 3228 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(d, eptr); | GETCHARINC(d, eptr); |
| if (d < 256) d = md->lcc[d]; | if (d < 256) d = md->lcc[d]; |
| if (fc == d) RRETURN(MATCH_NOMATCH); | if (fc == d) MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| else | else |
| Line 2624 for (;;) | Line 3247 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject || fc == md->lcc[*eptr++]) | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (fc == md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); | |
| } | } |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 2645 for (;;) | Line 3273 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(d, eptr, len); | GETCHARLEN(d, eptr, len); |
| if (d < 256) d = md->lcc[d]; | if (d < 256) d = md->lcc[d]; |
| if (fc == d) break; | if (fc == d) break; |
| Line 2666 for (;;) | Line 3298 for (;;) |
| { | { |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || fc == md->lcc[*eptr]) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| if (fc == md->lcc[*eptr]) break; | |
| eptr++; | eptr++; |
| } | } |
| if (possessive) continue; | if (possessive) continue; |
| Line 2678 for (;;) | Line 3315 for (;;) |
| } | } |
| } | } |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| } | } |
| Line 2694 for (;;) | Line 3331 for (;;) |
| register unsigned int d; | register unsigned int d; |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(d, eptr); | GETCHARINC(d, eptr); |
| if (fc == d) RRETURN(MATCH_NOMATCH); | if (fc == d) MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| else | else |
| Line 2703 for (;;) | Line 3345 for (;;) |
| /* Not UTF-8 mode */ | /* Not UTF-8 mode */ |
| { | { |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| if (fc == *eptr++) RRETURN(MATCH_NOMATCH); | { |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (fc == *eptr++) MRRETURN(MATCH_NOMATCH); | |
| } | |
| } | } |
| if (min == max) continue; | if (min == max) continue; |
| Line 2719 for (;;) | Line 3368 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(d, eptr); | GETCHARINC(d, eptr); |
| if (fc == d) RRETURN(MATCH_NOMATCH); | if (fc == d) MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| else | else |
| Line 2732 for (;;) | Line 3386 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject || fc == *eptr++) | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (fc == *eptr++) MRRETURN(MATCH_NOMATCH); | |
| } | } |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 2753 for (;;) | Line 3412 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(d, eptr, len); | GETCHARLEN(d, eptr, len); |
| if (fc == d) break; | if (fc == d) break; |
| eptr += len; | eptr += len; |
| Line 2773 for (;;) | Line 3436 for (;;) |
| { | { |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || fc == *eptr) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| if (fc == *eptr) break; | |
| eptr++; | eptr++; |
| } | } |
| if (possessive) continue; | if (possessive) continue; |
| Line 2785 for (;;) | Line 3453 for (;;) |
| } | } |
| } | } |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 2867 for (;;) | Line 3535 for (;;) |
| /* First, ensure the minimum number of matches are present. Use inline | /* First, ensure the minimum number of matches are present. Use inline |
| 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 |
| (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 | |
| 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 |
| and single-bytes. */ | and single-bytes. */ |
| if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); | |
| if (min > 0) | if (min > 0) |
| { | { |
| #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
| Line 2882 for (;;) | Line 3547 for (;;) |
| switch(prop_type) | switch(prop_type) |
| { | { |
| case PT_ANY: | case PT_ANY: |
| if (prop_fail_result) RRETURN(MATCH_NOMATCH); | if (prop_fail_result) MRRETURN(MATCH_NOMATCH); |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| } | } |
| break; | break; |
| Line 2893 for (;;) | Line 3562 for (;;) |
| case PT_LAMP: | case PT_LAMP: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| prop_chartype = UCD_CHARTYPE(c); | prop_chartype = UCD_CHARTYPE(c); |
| if ((prop_chartype == ucp_Lu || | if ((prop_chartype == ucp_Lu || |
| prop_chartype == ucp_Ll || | prop_chartype == ucp_Ll || |
| prop_chartype == ucp_Lt) == prop_fail_result) | prop_chartype == ucp_Lt) == prop_fail_result) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| break; | break; |
| case PT_GC: | case PT_GC: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| prop_category = UCD_CATEGORY(c); | prop_category = UCD_CATEGORY(c); |
| if ((prop_category == prop_value) == prop_fail_result) | if ((prop_category == prop_value) == prop_fail_result) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| break; | break; |
| case PT_PC: | case PT_PC: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| prop_chartype = UCD_CHARTYPE(c); | prop_chartype = UCD_CHARTYPE(c); |
| if ((prop_chartype == prop_value) == prop_fail_result) | if ((prop_chartype == prop_value) == prop_fail_result) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| break; | break; |
| case PT_SC: | case PT_SC: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| prop_script = UCD_SCRIPT(c); | prop_script = UCD_SCRIPT(c); |
| if ((prop_script == prop_value) == prop_fail_result) | if ((prop_script == prop_value) == prop_fail_result) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | |
| break; | |
| case PT_ALNUM: | |
| for (i = 1; i <= min; i++) | |
| { | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_L || prop_category == ucp_N) | |
| == prop_fail_result) | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| break; | |
| case PT_SPACE: /* Perl space */ | |
| for (i = 1; i <= min; i++) | |
| { | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL || | |
| c == CHAR_FF || c == CHAR_CR) | |
| == prop_fail_result) | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| break; | |
| case PT_PXSPACE: /* POSIX space */ | |
| for (i = 1; i <= min; i++) | |
| { | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL || | |
| c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) | |
| == prop_fail_result) | |
| MRRETURN(MATCH_NOMATCH); | |
| } | } |
| break; | break; |
| case PT_WORD: | |
| for (i = 1; i <= min; i++) | |
| { | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_L || prop_category == ucp_N || | |
| c == CHAR_UNDERSCORE) | |
| == prop_fail_result) | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| break; | |
| /* This should not occur */ | |
| default: | default: |
| RRETURN(PCRE_ERROR_INTERNAL); | RRETURN(PCRE_ERROR_INTERNAL); |
| } | } |
| Line 2948 for (;;) | Line 3702 for (;;) |
| { | { |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| prop_category = UCD_CATEGORY(c); | prop_category = UCD_CATEGORY(c); |
| if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH); | if (prop_category == ucp_M) MRRETURN(MATCH_NOMATCH); |
| while (eptr < md->end_subject) | while (eptr < md->end_subject) |
| { | { |
| int len = 1; | int len = 1; |
| if (!utf8) c = *eptr; else | if (!utf8) c = *eptr; |
| { | else { GETCHARLEN(c, eptr, len); } |
| GETCHARLEN(c, eptr, len); | |
| } | |
| prop_category = UCD_CATEGORY(c); | prop_category = UCD_CATEGORY(c); |
| if (prop_category != ucp_M) break; | if (prop_category != ucp_M) break; |
| eptr += len; | eptr += len; |
| Line 2976 for (;;) | Line 3733 for (;;) |
| case OP_ANY: | case OP_ANY: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject || IS_NEWLINE(eptr)) | if (eptr >= md->end_subject) |
| RRETURN(MATCH_NOMATCH); | { |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); | |
| eptr++; | eptr++; |
| while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; | while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; |
| } | } |
| Line 2986 for (;;) | Line 3747 for (;;) |
| case OP_ALLANY: | case OP_ALLANY: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| eptr++; | eptr++; |
| while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; | while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; |
| } | } |
| break; | break; |
| case OP_ANYBYTE: | case OP_ANYBYTE: |
| if (eptr > md->end_subject - min) MRRETURN(MATCH_NOMATCH); | |
| eptr += min; | eptr += min; |
| break; | break; |
| case OP_ANYNL: | case OP_ANYNL: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(c, eptr); | GETCHARINC(c, eptr); |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x000d: | case 0x000d: |
| if (eptr < md->end_subject && *eptr == 0x0a) eptr++; | if (eptr < md->end_subject && *eptr == 0x0a) eptr++; |
| break; | break; |
| Line 3016 for (;;) | Line 3786 for (;;) |
| case 0x0085: | case 0x0085: |
| case 0x2028: | case 0x2028: |
| case 0x2029: | case 0x2029: |
| if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); | if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| } | } |
| } | } |
| Line 3025 for (;;) | Line 3795 for (;;) |
| case OP_NOT_HSPACE: | case OP_NOT_HSPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(c, eptr); | GETCHARINC(c, eptr); |
| switch(c) | switch(c) |
| { | { |
| Line 3049 for (;;) | Line 3823 for (;;) |
| case 0x202f: /* NARROW NO-BREAK SPACE */ | case 0x202f: /* NARROW NO-BREAK SPACE */ |
| case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ | case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ |
| case 0x3000: /* IDEOGRAPHIC SPACE */ | case 0x3000: /* IDEOGRAPHIC SPACE */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| break; | break; |
| Line 3057 for (;;) | Line 3831 for (;;) |
| case OP_HSPACE: | case OP_HSPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(c, eptr); | GETCHARINC(c, eptr); |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x09: /* HT */ | case 0x09: /* HT */ |
| case 0x20: /* SPACE */ | case 0x20: /* SPACE */ |
| case 0xa0: /* NBSP */ | case 0xa0: /* NBSP */ |
| Line 3089 for (;;) | Line 3867 for (;;) |
| case OP_NOT_VSPACE: | case OP_NOT_VSPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(c, eptr); | GETCHARINC(c, eptr); |
| switch(c) | switch(c) |
| { | { |
| Line 3101 for (;;) | Line 3883 for (;;) |
| case 0x85: /* NEL */ | case 0x85: /* NEL */ |
| case 0x2028: /* LINE SEPARATOR */ | case 0x2028: /* LINE SEPARATOR */ |
| case 0x2029: /* PARAGRAPH SEPARATOR */ | case 0x2029: /* PARAGRAPH SEPARATOR */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| break; | break; |
| Line 3109 for (;;) | Line 3891 for (;;) |
| case OP_VSPACE: | case OP_VSPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(c, eptr); | GETCHARINC(c, eptr); |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x0a: /* LF */ | case 0x0a: /* LF */ |
| case 0x0b: /* VT */ | case 0x0b: /* VT */ |
| case 0x0c: /* FF */ | case 0x0c: /* FF */ |
| Line 3129 for (;;) | Line 3915 for (;;) |
| case OP_NOT_DIGIT: | case OP_NOT_DIGIT: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINC(c, eptr); | GETCHARINC(c, eptr); |
| if (c < 128 && (md->ctypes[c] & ctype_digit) != 0) | if (c < 128 && (md->ctypes[c] & ctype_digit) != 0) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| break; | break; |
| case OP_DIGIT: | case OP_DIGIT: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject || | if (eptr >= md->end_subject) |
| *eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0) | { |
| RRETURN(MATCH_NOMATCH); | SCHECK_PARTIAL(); |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0) | |
| MRRETURN(MATCH_NOMATCH); | |
| /* 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 */ |
| } | } |
| break; | break; |
| Line 3149 for (;;) | Line 3943 for (;;) |
| case OP_NOT_WHITESPACE: | case OP_NOT_WHITESPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject || | if (eptr >= md->end_subject) |
| (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0)) | { |
| RRETURN(MATCH_NOMATCH); | SCHECK_PARTIAL(); |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0) | |
| MRRETURN(MATCH_NOMATCH); | |
| while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80); | while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80); |
| } | } |
| break; | break; |
| Line 3159 for (;;) | Line 3957 for (;;) |
| case OP_WHITESPACE: | case OP_WHITESPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject || | if (eptr >= md->end_subject) |
| *eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0) | { |
| RRETURN(MATCH_NOMATCH); | SCHECK_PARTIAL(); |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0) | |
| MRRETURN(MATCH_NOMATCH); | |
| /* 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 */ |
| } | } |
| break; | break; |
| Line 3169 for (;;) | Line 3971 for (;;) |
| case OP_NOT_WORDCHAR: | case OP_NOT_WORDCHAR: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject || | if (eptr >= md->end_subject) |
| (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0)) | { |
| RRETURN(MATCH_NOMATCH); | SCHECK_PARTIAL(); |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0) | |
| MRRETURN(MATCH_NOMATCH); | |
| while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80); | while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80); |
| } | } |
| break; | break; |
| Line 3179 for (;;) | Line 3985 for (;;) |
| case OP_WORDCHAR: | case OP_WORDCHAR: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject || | if (eptr >= md->end_subject) |
| *eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0) | { |
| RRETURN(MATCH_NOMATCH); | SCHECK_PARTIAL(); |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0) | |
| MRRETURN(MATCH_NOMATCH); | |
| /* 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 */ |
| } | } |
| break; | break; |
| Line 3194 for (;;) | Line 4004 for (;;) |
| #endif /* SUPPORT_UTF8 */ | #endif /* SUPPORT_UTF8 */ |
| /* 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 |
| 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. */ | |
| switch(ctype) | switch(ctype) |
| { | { |
| case OP_ANY: | case OP_ANY: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); | |
| eptr++; | eptr++; |
| } | } |
| break; | break; |
| case OP_ALLANY: | case OP_ALLANY: |
| if (eptr > md->end_subject - min) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| eptr += min; | eptr += min; |
| break; | break; |
| case OP_ANYBYTE: | case OP_ANYBYTE: |
| if (eptr > md->end_subject - min) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| eptr += min; | eptr += min; |
| break; | break; |
| /* Because of the CRLF case, we can't assume the minimum number of | |
| bytes are present in this case. */ | |
| case OP_ANYNL: | case OP_ANYNL: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| switch(*eptr++) | switch(*eptr++) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x000d: | case 0x000d: |
| if (eptr < md->end_subject && *eptr == 0x0a) eptr++; | if (eptr < md->end_subject && *eptr == 0x0a) eptr++; |
| break; | break; |
| Line 3234 for (;;) | Line 4059 for (;;) |
| case 0x000b: | case 0x000b: |
| case 0x000c: | case 0x000c: |
| case 0x0085: | case 0x0085: |
| if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); | if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| } | } |
| } | } |
| Line 3243 for (;;) | Line 4068 for (;;) |
| case OP_NOT_HSPACE: | case OP_NOT_HSPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| switch(*eptr++) | switch(*eptr++) |
| { | { |
| default: break; | default: break; |
| case 0x09: /* HT */ | case 0x09: /* HT */ |
| case 0x20: /* SPACE */ | case 0x20: /* SPACE */ |
| case 0xa0: /* NBSP */ | case 0xa0: /* NBSP */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| break; | break; |
| Line 3258 for (;;) | Line 4087 for (;;) |
| case OP_HSPACE: | case OP_HSPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| switch(*eptr++) | switch(*eptr++) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x09: /* HT */ | case 0x09: /* HT */ |
| case 0x20: /* SPACE */ | case 0x20: /* SPACE */ |
| case 0xa0: /* NBSP */ | case 0xa0: /* NBSP */ |
| Line 3273 for (;;) | Line 4106 for (;;) |
| case OP_NOT_VSPACE: | case OP_NOT_VSPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| switch(*eptr++) | switch(*eptr++) |
| { | { |
| default: break; | default: break; |
| Line 3282 for (;;) | Line 4119 for (;;) |
| case 0x0c: /* FF */ | case 0x0c: /* FF */ |
| case 0x0d: /* CR */ | case 0x0d: /* CR */ |
| case 0x85: /* NEL */ | case 0x85: /* NEL */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| } | } |
| break; | break; |
| Line 3290 for (;;) | Line 4127 for (;;) |
| case OP_VSPACE: | case OP_VSPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | { |
| if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| switch(*eptr++) | switch(*eptr++) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x0a: /* LF */ | case 0x0a: /* LF */ |
| case 0x0b: /* VT */ | case 0x0b: /* VT */ |
| case 0x0c: /* FF */ | case 0x0c: /* FF */ |
| Line 3306 for (;;) | Line 4147 for (;;) |
| case OP_NOT_DIGIT: | case OP_NOT_DIGIT: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); | { |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if ((md->ctypes[*eptr++] & ctype_digit) != 0) MRRETURN(MATCH_NOMATCH); | |
| } | |
| break; | break; |
| case OP_DIGIT: | case OP_DIGIT: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| if ((md->ctypes[*eptr++] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); | { |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if ((md->ctypes[*eptr++] & ctype_digit) == 0) MRRETURN(MATCH_NOMATCH); | |
| } | |
| break; | break; |
| case OP_NOT_WHITESPACE: | case OP_NOT_WHITESPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| if ((md->ctypes[*eptr++] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); | { |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if ((md->ctypes[*eptr++] & ctype_space) != 0) MRRETURN(MATCH_NOMATCH); | |
| } | |
| break; | break; |
| case OP_WHITESPACE: | case OP_WHITESPACE: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| if ((md->ctypes[*eptr++] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); | { |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if ((md->ctypes[*eptr++] & ctype_space) == 0) MRRETURN(MATCH_NOMATCH); | |
| } | |
| break; | break; |
| case OP_NOT_WORDCHAR: | case OP_NOT_WORDCHAR: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if ((md->ctypes[*eptr++] & ctype_word) != 0) | if ((md->ctypes[*eptr++] & ctype_word) != 0) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | |
| break; | break; |
| case OP_WORDCHAR: | case OP_WORDCHAR: |
| for (i = 1; i <= min; i++) | for (i = 1; i <= min; i++) |
| { | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if ((md->ctypes[*eptr++] & ctype_word) == 0) | if ((md->ctypes[*eptr++] & ctype_word) == 0) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | |
| break; | break; |
| default: | default: |
| Line 3361 for (;;) | Line 4244 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| GETCHARINC(c, eptr); | if (eptr >= md->end_subject) |
| if (prop_fail_result) RRETURN(MATCH_NOMATCH); | { |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| if (prop_fail_result) MRRETURN(MATCH_NOMATCH); | |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 3372 for (;;) | Line 4260 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| GETCHARINC(c, eptr); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_chartype = UCD_CHARTYPE(c); | prop_chartype = UCD_CHARTYPE(c); |
| if ((prop_chartype == ucp_Lu || | if ((prop_chartype == ucp_Lu || |
| prop_chartype == ucp_Ll || | prop_chartype == ucp_Ll || |
| prop_chartype == ucp_Lt) == prop_fail_result) | prop_chartype == ucp_Lt) == prop_fail_result) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 3387 for (;;) | Line 4280 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| GETCHARINC(c, eptr); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_category = UCD_CATEGORY(c); | prop_category = UCD_CATEGORY(c); |
| if ((prop_category == prop_value) == prop_fail_result) | if ((prop_category == prop_value) == prop_fail_result) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 3400 for (;;) | Line 4298 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| GETCHARINC(c, eptr); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_chartype = UCD_CHARTYPE(c); | prop_chartype = UCD_CHARTYPE(c); |
| if ((prop_chartype == prop_value) == prop_fail_result) | if ((prop_chartype == prop_value) == prop_fail_result) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 3413 for (;;) | Line 4316 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| GETCHARINC(c, eptr); | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_script = UCD_SCRIPT(c); | prop_script = UCD_SCRIPT(c); |
| if ((prop_script == prop_value) == prop_fail_result) | if ((prop_script == prop_value) == prop_fail_result) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | |
| /* Control never gets here */ | |
| case PT_ALNUM: | |
| for (fi = min;; fi++) | |
| { | |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM59); | |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | |
| if (fi >= max) MRRETURN(MATCH_NOMATCH); | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_L || prop_category == ucp_N) | |
| == prop_fail_result) | |
| MRRETURN(MATCH_NOMATCH); | |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| case PT_SPACE: /* Perl space */ | |
| for (fi = min;; fi++) | |
| { | |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM60); | |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | |
| if (fi >= max) MRRETURN(MATCH_NOMATCH); | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL || | |
| c == CHAR_FF || c == CHAR_CR) | |
| == prop_fail_result) | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| /* Control never gets here */ | |
| case PT_PXSPACE: /* POSIX space */ | |
| for (fi = min;; fi++) | |
| { | |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM61); | |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | |
| if (fi >= max) MRRETURN(MATCH_NOMATCH); | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL || | |
| c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) | |
| == prop_fail_result) | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| /* Control never gets here */ | |
| case PT_WORD: | |
| for (fi = min;; fi++) | |
| { | |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM62); | |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | |
| if (fi >= max) MRRETURN(MATCH_NOMATCH); | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_L || | |
| prop_category == ucp_N || | |
| c == CHAR_UNDERSCORE) | |
| == prop_fail_result) | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| /* Control never gets here */ | |
| /* This should never occur */ | |
| default: | default: |
| RRETURN(PCRE_ERROR_INTERNAL); | RRETURN(PCRE_ERROR_INTERNAL); |
| } | } |
| Line 3435 for (;;) | Line 4425 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| prop_category = UCD_CATEGORY(c); | prop_category = UCD_CATEGORY(c); |
| if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH); | if (prop_category == ucp_M) MRRETURN(MATCH_NOMATCH); |
| while (eptr < md->end_subject) | while (eptr < md->end_subject) |
| { | { |
| int len = 1; | int len = 1; |
| if (!utf8) c = *eptr; else | if (!utf8) c = *eptr; |
| { | else { GETCHARLEN(c, eptr, len); } |
| GETCHARLEN(c, eptr, len); | |
| } | |
| prop_category = UCD_CATEGORY(c); | prop_category = UCD_CATEGORY(c); |
| if (prop_category != ucp_M) break; | if (prop_category != ucp_M) break; |
| eptr += len; | eptr += len; |
| Line 3464 for (;;) | Line 4457 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject || | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| (ctype == OP_ANY && IS_NEWLINE(eptr))) | if (eptr >= md->end_subject) |
| RRETURN(MATCH_NOMATCH); | { |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (ctype == OP_ANY && IS_NEWLINE(eptr)) | |
| MRRETURN(MATCH_NOMATCH); | |
| GETCHARINC(c, eptr); | GETCHARINC(c, eptr); |
| switch(ctype) | switch(ctype) |
| { | { |
| Line 3479 for (;;) | Line 4476 for (;;) |
| case OP_ANYNL: | case OP_ANYNL: |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x000d: | case 0x000d: |
| if (eptr < md->end_subject && *eptr == 0x0a) eptr++; | if (eptr < md->end_subject && *eptr == 0x0a) eptr++; |
| break; | break; |
| Line 3491 for (;;) | Line 4488 for (;;) |
| case 0x0085: | case 0x0085: |
| case 0x2028: | case 0x2028: |
| case 0x2029: | case 0x2029: |
| if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); | if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| } | } |
| break; | break; |
| Line 3519 for (;;) | Line 4516 for (;;) |
| case 0x202f: /* NARROW NO-BREAK SPACE */ | case 0x202f: /* NARROW NO-BREAK SPACE */ |
| case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ | case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ |
| case 0x3000: /* IDEOGRAPHIC SPACE */ | case 0x3000: /* IDEOGRAPHIC SPACE */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| break; | break; |
| case OP_HSPACE: | case OP_HSPACE: |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x09: /* HT */ | case 0x09: /* HT */ |
| case 0x20: /* SPACE */ | case 0x20: /* SPACE */ |
| case 0xa0: /* NBSP */ | case 0xa0: /* NBSP */ |
| Line 3561 for (;;) | Line 4558 for (;;) |
| case 0x85: /* NEL */ | case 0x85: /* NEL */ |
| case 0x2028: /* LINE SEPARATOR */ | case 0x2028: /* LINE SEPARATOR */ |
| case 0x2029: /* PARAGRAPH SEPARATOR */ | case 0x2029: /* PARAGRAPH SEPARATOR */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| break; | break; |
| case OP_VSPACE: | case OP_VSPACE: |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x0a: /* LF */ | case 0x0a: /* LF */ |
| case 0x0b: /* VT */ | case 0x0b: /* VT */ |
| case 0x0c: /* FF */ | case 0x0c: /* FF */ |
| Line 3582 for (;;) | Line 4579 for (;;) |
| case OP_NOT_DIGIT: | case OP_NOT_DIGIT: |
| if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) | if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case OP_DIGIT: | case OP_DIGIT: |
| if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0) | if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case OP_NOT_WHITESPACE: | case OP_NOT_WHITESPACE: |
| if (c < 256 && (md->ctypes[c] & ctype_space) != 0) | if (c < 256 && (md->ctypes[c] & ctype_space) != 0) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case OP_WHITESPACE: | case OP_WHITESPACE: |
| if (c >= 256 || (md->ctypes[c] & ctype_space) == 0) | if (c >= 256 || (md->ctypes[c] & ctype_space) == 0) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case OP_NOT_WORDCHAR: | case OP_NOT_WORDCHAR: |
| if (c < 256 && (md->ctypes[c] & ctype_word) != 0) | if (c < 256 && (md->ctypes[c] & ctype_word) != 0) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case OP_WORDCHAR: | case OP_WORDCHAR: |
| if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) | if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| default: | default: |
| Line 3623 for (;;) | Line 4620 for (;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43); |
| if (rrc != MATCH_NOMATCH) RRETURN(rrc); | if (rrc != MATCH_NOMATCH) RRETURN(rrc); |
| if (fi >= max || eptr >= md->end_subject || | if (fi >= max) MRRETURN(MATCH_NOMATCH); |
| (ctype == OP_ANY && IS_NEWLINE(eptr))) | if (eptr >= md->end_subject) |
| RRETURN(MATCH_NOMATCH); | { |
| SCHECK_PARTIAL(); | |
| MRRETURN(MATCH_NOMATCH); | |
| } | |
| if (ctype == OP_ANY && IS_NEWLINE(eptr)) | |
| MRRETURN(MATCH_NOMATCH); | |
| c = *eptr++; | c = *eptr++; |
| switch(ctype) | switch(ctype) |
| { | { |
| Line 3638 for (;;) | Line 4639 for (;;) |
| case OP_ANYNL: | case OP_ANYNL: |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x000d: | case 0x000d: |
| if (eptr < md->end_subject && *eptr == 0x0a) eptr++; | if (eptr < md->end_subject && *eptr == 0x0a) eptr++; |
| break; | break; |
| Line 3649 for (;;) | Line 4650 for (;;) |
| case 0x000b: | case 0x000b: |
| case 0x000c: | case 0x000c: |
| case 0x0085: | case 0x0085: |
| if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); | if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| } | } |
| break; | break; |
| Line 3661 for (;;) | Line 4662 for (;;) |
| case 0x09: /* HT */ | case 0x09: /* HT */ |
| case 0x20: /* SPACE */ | case 0x20: /* SPACE */ |
| case 0xa0: /* NBSP */ | case 0xa0: /* NBSP */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| break; | break; |
| case OP_HSPACE: | case OP_HSPACE: |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x09: /* HT */ | case 0x09: /* HT */ |
| case 0x20: /* SPACE */ | case 0x20: /* SPACE */ |
| case 0xa0: /* NBSP */ | case 0xa0: /* NBSP */ |
| Line 3685 for (;;) | Line 4686 for (;;) |
| case 0x0c: /* FF */ | case 0x0c: /* FF */ |
| case 0x0d: /* CR */ | case 0x0d: /* CR */ |
| case 0x85: /* NEL */ | case 0x85: /* NEL */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| break; | break; |
| case OP_VSPACE: | case OP_VSPACE: |
| switch(c) | switch(c) |
| { | { |
| default: RRETURN(MATCH_NOMATCH); | default: MRRETURN(MATCH_NOMATCH); |
| case 0x0a: /* LF */ | case 0x0a: /* LF */ |
| case 0x0b: /* VT */ | case 0x0b: /* VT */ |
| case 0x0c: /* FF */ | case 0x0c: /* FF */ |
| Line 3703 for (;;) | Line 4704 for (;;) |
| break; | break; |
| case OP_NOT_DIGIT: | case OP_NOT_DIGIT: |
| if ((md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); | if ((md->ctypes[c] & ctype_digit) != 0) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case OP_DIGIT: | case OP_DIGIT: |
| if ((md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); | if ((md->ctypes[c] & ctype_digit) == 0) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case OP_NOT_WHITESPACE: | case OP_NOT_WHITESPACE: |
| if ((md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); | if ((md->ctypes[c] & ctype_space) != 0) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case OP_WHITESPACE: | case OP_WHITESPACE: |
| if ((md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); | if ((md->ctypes[c] & ctype_space) == 0) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case OP_NOT_WORDCHAR: | case OP_NOT_WORDCHAR: |
| if ((md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); | if ((md->ctypes[c] & ctype_word) != 0) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| case OP_WORDCHAR: | case OP_WORDCHAR: |
| if ((md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); | if ((md->ctypes[c] & ctype_word) == 0) MRRETURN(MATCH_NOMATCH); |
| break; | break; |
| default: | default: |
| Line 3751 for (;;) | Line 4752 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| GETCHARLEN(c, eptr, len); | { |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLENTEST(c, eptr, len); | |
| if (prop_fail_result) break; | if (prop_fail_result) break; |
| eptr+= len; | eptr+= len; |
| } | } |
| Line 3762 for (;;) | Line 4767 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| GETCHARLEN(c, eptr, len); | { |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLENTEST(c, eptr, len); | |
| prop_chartype = UCD_CHARTYPE(c); | prop_chartype = UCD_CHARTYPE(c); |
| if ((prop_chartype == ucp_Lu || | if ((prop_chartype == ucp_Lu || |
| prop_chartype == ucp_Ll || | prop_chartype == ucp_Ll || |
| Line 3777 for (;;) | Line 4786 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| GETCHARLEN(c, eptr, len); | { |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLENTEST(c, eptr, len); | |
| prop_category = UCD_CATEGORY(c); | prop_category = UCD_CATEGORY(c); |
| if ((prop_category == prop_value) == prop_fail_result) | if ((prop_category == prop_value) == prop_fail_result) |
| break; | break; |
| Line 3790 for (;;) | Line 4803 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| GETCHARLEN(c, eptr, len); | { |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLENTEST(c, eptr, len); | |
| prop_chartype = UCD_CHARTYPE(c); | prop_chartype = UCD_CHARTYPE(c); |
| if ((prop_chartype == prop_value) == prop_fail_result) | if ((prop_chartype == prop_value) == prop_fail_result) |
| break; | break; |
| Line 3803 for (;;) | Line 4820 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| GETCHARLEN(c, eptr, len); | { |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLENTEST(c, eptr, len); | |
| prop_script = UCD_SCRIPT(c); | prop_script = UCD_SCRIPT(c); |
| if ((prop_script == prop_value) == prop_fail_result) | if ((prop_script == prop_value) == prop_fail_result) |
| break; | break; |
| eptr+= len; | eptr+= len; |
| } | } |
| break; | break; |
| case PT_ALNUM: | |
| for (i = min; i < max; i++) | |
| { | |
| int len = 1; | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLENTEST(c, eptr, len); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_L || prop_category == ucp_N) | |
| == prop_fail_result) | |
| break; | |
| eptr+= len; | |
| } | |
| break; | |
| case PT_SPACE: /* Perl space */ | |
| for (i = min; i < max; i++) | |
| { | |
| int len = 1; | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLENTEST(c, eptr, len); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL || | |
| c == CHAR_FF || c == CHAR_CR) | |
| == prop_fail_result) | |
| break; | |
| eptr+= len; | |
| } | |
| break; | |
| case PT_PXSPACE: /* POSIX space */ | |
| for (i = min; i < max; i++) | |
| { | |
| int len = 1; | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLENTEST(c, eptr, len); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL || | |
| c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) | |
| == prop_fail_result) | |
| break; | |
| eptr+= len; | |
| } | |
| break; | |
| case PT_WORD: | |
| for (i = min; i < max; i++) | |
| { | |
| int len = 1; | |
| if (eptr >= md->end_subject) | |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLENTEST(c, eptr, len); | |
| prop_category = UCD_CATEGORY(c); | |
| if ((prop_category == ucp_L || prop_category == ucp_N || | |
| c == CHAR_UNDERSCORE) == prop_fail_result) | |
| break; | |
| eptr+= len; | |
| } | |
| break; | |
| default: | |
| RRETURN(PCRE_ERROR_INTERNAL); | |
| } | } |
| /* eptr is now past the end of the maximum run */ | /* eptr is now past the end of the maximum run */ |
| Line 3832 for (;;) | Line 4930 for (;;) |
| { | { |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARINCTEST(c, eptr); | GETCHARINCTEST(c, eptr); |
| prop_category = UCD_CATEGORY(c); | prop_category = UCD_CATEGORY(c); |
| if (prop_category == ucp_M) break; | if (prop_category == ucp_M) break; |
| Line 3852 for (;;) | Line 4954 for (;;) |
| /* eptr is now past the end of the maximum run */ | /* eptr is now past the end of the maximum run */ |
| if (possessive) continue; | if (possessive) continue; |
| for(;;) | for(;;) |
| { | { |
| RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM45); | RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM45); |
| Line 3887 for (;;) | Line 4990 for (;;) |
| { | { |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || IS_NEWLINE(eptr)) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| if (IS_NEWLINE(eptr)) break; | |
| eptr++; | eptr++; |
| while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; | while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; |
| } | } |
| Line 3899 for (;;) | Line 5007 for (;;) |
| { | { |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || IS_NEWLINE(eptr)) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| if (IS_NEWLINE(eptr)) break; | |
| eptr++; | eptr++; |
| while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; | while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; |
| } | } |
| Line 3911 for (;;) | Line 5024 for (;;) |
| { | { |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| eptr++; | eptr++; |
| while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; | while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; |
| } | } |
| Line 3924 for (;;) | Line 5041 for (;;) |
| case OP_ANYBYTE: | case OP_ANYBYTE: |
| c = max - min; | c = max - min; |
| if (c > (unsigned int)(md->end_subject - eptr)) | if (c > (unsigned int)(md->end_subject - eptr)) |
| c = md->end_subject - eptr; | { |
| eptr += c; | eptr = md->end_subject; |
| SCHECK_PARTIAL(); | |
| } | |
| else eptr += c; | |
| break; | break; |
| case OP_ANYNL: | case OP_ANYNL: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(c, eptr, len); | GETCHARLEN(c, eptr, len); |
| if (c == 0x000d) | if (c == 0x000d) |
| { | { |
| Line 3957 for (;;) | Line 5081 for (;;) |
| { | { |
| BOOL gotspace; | BOOL gotspace; |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(c, eptr, len); | GETCHARLEN(c, eptr, len); |
| switch(c) | switch(c) |
| { | { |
| Line 3995 for (;;) | Line 5123 for (;;) |
| { | { |
| BOOL gotspace; | BOOL gotspace; |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(c, eptr, len); | GETCHARLEN(c, eptr, len); |
| switch(c) | switch(c) |
| { | { |
| Line 4019 for (;;) | Line 5151 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(c, eptr, len); | GETCHARLEN(c, eptr, len); |
| if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break; | if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break; |
| eptr+= len; | eptr+= len; |
| Line 4030 for (;;) | Line 5166 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(c, eptr, len); | GETCHARLEN(c, eptr, len); |
| if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break; | if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break; |
| eptr+= len; | eptr+= len; |
| Line 4041 for (;;) | Line 5181 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(c, eptr, len); | GETCHARLEN(c, eptr, len); |
| if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break; | if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break; |
| eptr+= len; | eptr+= len; |
| Line 4052 for (;;) | Line 5196 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(c, eptr, len); | GETCHARLEN(c, eptr, len); |
| if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break; | if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break; |
| eptr+= len; | eptr+= len; |
| Line 4063 for (;;) | Line 5211 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(c, eptr, len); | GETCHARLEN(c, eptr, len); |
| if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break; | if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break; |
| eptr+= len; | eptr+= len; |
| Line 4074 for (;;) | Line 5226 for (;;) |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| int len = 1; | int len = 1; |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| GETCHARLEN(c, eptr, len); | GETCHARLEN(c, eptr, len); |
| if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break; | if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break; |
| eptr+= len; | eptr+= len; |
| Line 4106 for (;;) | Line 5262 for (;;) |
| case OP_ANY: | case OP_ANY: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || IS_NEWLINE(eptr)) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| if (IS_NEWLINE(eptr)) break; | |
| eptr++; | eptr++; |
| } | } |
| break; | break; |
| Line 4115 for (;;) | Line 5276 for (;;) |
| case OP_ANYBYTE: | case OP_ANYBYTE: |
| c = max - min; | c = max - min; |
| if (c > (unsigned int)(md->end_subject - eptr)) | if (c > (unsigned int)(md->end_subject - eptr)) |
| c = md->end_subject - eptr; | { |
| eptr += c; | eptr = md->end_subject; |
| SCHECK_PARTIAL(); | |
| } | |
| else eptr += c; | |
| break; | break; |
| case OP_ANYNL: | case OP_ANYNL: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| c = *eptr; | c = *eptr; |
| if (c == 0x000d) | if (c == 0x000d) |
| { | { |
| Line 4143 for (;;) | Line 5311 for (;;) |
| case OP_NOT_HSPACE: | case OP_NOT_HSPACE: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| c = *eptr; | c = *eptr; |
| if (c == 0x09 || c == 0x20 || c == 0xa0) break; | if (c == 0x09 || c == 0x20 || c == 0xa0) break; |
| eptr++; | eptr++; |
| Line 4153 for (;;) | Line 5325 for (;;) |
| case OP_HSPACE: | case OP_HSPACE: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| c = *eptr; | c = *eptr; |
| if (c != 0x09 && c != 0x20 && c != 0xa0) break; | if (c != 0x09 && c != 0x20 && c != 0xa0) break; |
| eptr++; | eptr++; |
| Line 4163 for (;;) | Line 5339 for (;;) |
| case OP_NOT_VSPACE: | case OP_NOT_VSPACE: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| c = *eptr; | c = *eptr; |
| if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85) | if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85) |
| break; | break; |
| Line 4174 for (;;) | Line 5354 for (;;) |
| case OP_VSPACE: | case OP_VSPACE: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject) break; | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | |
| } | |
| c = *eptr; | c = *eptr; |
| if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85) | if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85) |
| break; | break; |
| Line 4185 for (;;) | Line 5369 for (;;) |
| case OP_NOT_DIGIT: | case OP_NOT_DIGIT: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0) | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | break; |
| } | |
| if ((md->ctypes[*eptr] & ctype_digit) != 0) break; | |
| eptr++; | eptr++; |
| } | } |
| break; | break; |
| Line 4194 for (;;) | Line 5382 for (;;) |
| case OP_DIGIT: | case OP_DIGIT: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0) | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | break; |
| } | |
| if ((md->ctypes[*eptr] & ctype_digit) == 0) break; | |
| eptr++; | eptr++; |
| } | } |
| break; | break; |
| Line 4203 for (;;) | Line 5395 for (;;) |
| case OP_NOT_WHITESPACE: | case OP_NOT_WHITESPACE: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0) | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | break; |
| } | |
| if ((md->ctypes[*eptr] & ctype_space) != 0) break; | |
| eptr++; | eptr++; |
| } | } |
| break; | break; |
| Line 4212 for (;;) | Line 5408 for (;;) |
| case OP_WHITESPACE: | case OP_WHITESPACE: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0) | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | break; |
| } | |
| if ((md->ctypes[*eptr] & ctype_space) == 0) break; | |
| eptr++; | eptr++; |
| } | } |
| break; | break; |
| Line 4221 for (;;) | Line 5421 for (;;) |
| case OP_NOT_WORDCHAR: | case OP_NOT_WORDCHAR: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0) | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | break; |
| } | |
| if ((md->ctypes[*eptr] & ctype_word) != 0) break; | |
| eptr++; | eptr++; |
| } | } |
| break; | break; |
| Line 4230 for (;;) | Line 5434 for (;;) |
| case OP_WORDCHAR: | case OP_WORDCHAR: |
| for (i = min; i < max; i++) | for (i = min; i < max; i++) |
| { | { |
| if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0) | if (eptr >= md->end_subject) |
| { | |
| SCHECK_PARTIAL(); | |
| break; | break; |
| } | |
| if ((md->ctypes[*eptr] & ctype_word) == 0) break; | |
| eptr++; | eptr++; |
| } | } |
| break; | break; |
| Line 4253 for (;;) | Line 5461 for (;;) |
| /* Get here if we can't make it match with any permitted repetitions */ | /* Get here if we can't make it match with any permitted repetitions */ |
| RRETURN(MATCH_NOMATCH); | MRRETURN(MATCH_NOMATCH); |
| } | } |
| /* Control never gets here */ | /* Control never gets here */ |
| Line 4286 switch (frame->Xwhere) | Line 5494 switch (frame->Xwhere) |
| LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17) | LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17) |
| LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33) | LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33) |
| LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52) | LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52) |
| LBL(53) LBL(54) | LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58) |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| LBL(16) LBL(18) LBL(20) LBL(21) LBL(22) LBL(23) LBL(28) LBL(30) | LBL(16) LBL(18) LBL(20) LBL(21) LBL(22) LBL(23) LBL(28) LBL(30) |
| LBL(32) LBL(34) LBL(42) LBL(46) | LBL(32) LBL(34) LBL(42) LBL(46) |
| #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
| LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45) | LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45) |
| LBL(59) LBL(60) LBL(61) LBL(62) | |
| #endif /* SUPPORT_UCP */ | #endif /* SUPPORT_UCP */ |
| #endif /* SUPPORT_UTF8 */ | #endif /* SUPPORT_UTF8 */ |
| default: | default: |
| Line 4409 const uschar *tables; | Line 5618 const uschar *tables; |
| const uschar *start_bits = NULL; | const uschar *start_bits = NULL; |
| USPTR start_match = (USPTR)subject + start_offset; | USPTR start_match = (USPTR)subject + start_offset; |
| USPTR end_subject; | USPTR end_subject; |
| USPTR start_partial = NULL; | |
| USPTR req_byte_ptr = start_match - 1; | USPTR req_byte_ptr = start_match - 1; |
| pcre_study_data internal_study; | pcre_study_data internal_study; |
| Line 4424 if ((options & ~PUBLIC_EXEC_OPTIONS) != | Line 5634 if ((options & ~PUBLIC_EXEC_OPTIONS) != |
| if (re == NULL || subject == NULL || | if (re == NULL || subject == NULL || |
| (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; | (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; |
| if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; | if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; |
| if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET; | |
| /* This information is for finding all the numbers associated with a given | |
| name, for condition testing. */ | |
| md->name_table = (uschar *)re + re->name_table_offset; | |
| md->name_count = re->name_count; | |
| md->name_entry_size = re->name_entry_size; | |
| /* Fish out the optional data from the extra_data structure, first setting | /* Fish out the optional data from the extra_data structure, first setting |
| the default values. */ | the default values. */ |
| Line 4487 end_subject = md->end_subject; | Line 5705 end_subject = md->end_subject; |
| md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; | md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; |
| utf8 = md->utf8 = (re->options & PCRE_UTF8) != 0; | utf8 = md->utf8 = (re->options & PCRE_UTF8) != 0; |
| md->use_ucp = (re->options & PCRE_UCP) != 0; | |
| md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0; | md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0; |
| md->notbol = (options & PCRE_NOTBOL) != 0; | md->notbol = (options & PCRE_NOTBOL) != 0; |
| md->noteol = (options & PCRE_NOTEOL) != 0; | md->noteol = (options & PCRE_NOTEOL) != 0; |
| md->notempty = (options & PCRE_NOTEMPTY) != 0; | md->notempty = (options & PCRE_NOTEMPTY) != 0; |
| md->partial = (options & PCRE_PARTIAL) != 0; | md->notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0; |
| md->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 : | |
| ((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0; | |
| md->hitend = FALSE; | md->hitend = FALSE; |
| md->mark = NULL; /* In case never set */ | |
| md->recursive = NULL; /* No recursion at top level */ | md->recursive = NULL; /* No recursion at top level */ |
| Line 4533 switch ((((options & PCRE_NEWLINE_BITS) | Line 5755 switch ((((options & PCRE_NEWLINE_BITS) |
| (pcre_uint32)options) & PCRE_NEWLINE_BITS) | (pcre_uint32)options) & PCRE_NEWLINE_BITS) |
| { | { |
| case 0: newline = NEWLINE; break; /* Compile-time default */ | case 0: newline = NEWLINE; break; /* Compile-time default */ |
| case PCRE_NEWLINE_CR: newline = '\r'; break; | case PCRE_NEWLINE_CR: newline = CHAR_CR; break; |
| case PCRE_NEWLINE_LF: newline = '\n'; break; | case PCRE_NEWLINE_LF: newline = CHAR_NL; break; |
| case PCRE_NEWLINE_CR+ | case PCRE_NEWLINE_CR+ |
| PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; break; | PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break; |
| case PCRE_NEWLINE_ANY: newline = -1; break; | case PCRE_NEWLINE_ANY: newline = -1; break; |
| case PCRE_NEWLINE_ANYCRLF: newline = -2; break; | case PCRE_NEWLINE_ANYCRLF: newline = -2; break; |
| default: return PCRE_ERROR_BADNEWLINE; | default: return PCRE_ERROR_BADNEWLINE; |
| Line 4566 else | Line 5788 else |
| } | } |
| } | } |
| /* Partial matching is supported only for a restricted set of regexes at the | /* Partial matching was originally supported only for a restricted set of |
| moment. */ | regexes; from release 8.00 there are no restrictions, but the bits are still |
| defined (though never set). So there's no harm in leaving this code. */ | |
| if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0) | if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0) |
| return PCRE_ERROR_BADPARTIAL; | return PCRE_ERROR_BADPARTIAL; |
| Line 4578 back the character offset. */ | Line 5801 back the character offset. */ |
| #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF8 |
| if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0) | if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0) |
| { | { |
| if (_pcre_valid_utf8((uschar *)subject, length) >= 0) | int tb; |
| return PCRE_ERROR_BADUTF8; | if ((tb = _pcre_valid_utf8((USPTR)subject, length)) >= 0) |
| return (tb == length && md->partial > 1)? | |
| PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8; | |
| if (start_offset > 0 && start_offset < length) | if (start_offset > 0 && start_offset < length) |
| { | { |
| int tb = ((uschar *)subject)[start_offset]; | tb = ((USPTR)subject)[start_offset] & 0xc0; |
| if (tb > 127) | if (tb == 0x80) return PCRE_ERROR_BADUTF8_OFFSET; |
| { | |
| tb &= 0xc0; | |
| if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET; | |
| } | |
| } | } |
| } | } |
| #endif | #endif |
| Line 4654 if (!anchored) | Line 5875 if (!anchored) |
| } | } |
| else | else |
| if (!startline && study != NULL && | if (!startline && study != NULL && |
| (study->options & PCRE_STUDY_MAPPED) != 0) | (study->flags & PCRE_STUDY_MAPPED) != 0) |
| start_bits = study->start_bits; | start_bits = study->start_bits; |
| } | } |
| Line 4688 for(;;) | Line 5909 for(;;) |
| while (iptr < iend) *iptr++ = -1; | while (iptr < iend) *iptr++ = -1; |
| } | } |
| /* Advance to a unique first char if possible. If firstline is TRUE, the | /* If firstline is TRUE, the start of the match is constrained to the first |
| start of the match is constrained to the first line of a multiline string. | line of a multiline string. That is, the match must be before or at the first |
| That is, the match must be before or at the first newline. Implement this by | newline. Implement this by temporarily adjusting end_subject so that we stop |
| temporarily adjusting end_subject so that we stop scanning at a newline. If | scanning at a newline. If the match fails at the newline, later code breaks |
| the match fails at the newline, later code breaks this loop. */ | this loop. */ |
| if (firstline) | if (firstline) |
| { | { |
| Line 4712 for(;;) | Line 5933 for(;;) |
| end_subject = t; | end_subject = t; |
| } | } |
| /* Now advance to a unique first byte if there is one. */ | /* There are some optimizations that avoid running the match if a known |
| starting point is not found, or if a known later character is not present. | |
| However, there is an option that disables these, for testing and for ensuring | |
| that all callouts do actually occur. The option can be set in the regex by | |
| (*NO_START_OPT) or passed in match-time options. */ | |
| if (first_byte >= 0) | if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0) |
| { | { |
| if (first_byte_caseless) | /* Advance to a unique first byte if there is one. */ |
| while (start_match < end_subject && md->lcc[*start_match] != first_byte) | |
| start_match++; | |
| else | |
| while (start_match < end_subject && *start_match != first_byte) | |
| start_match++; | |
| } | |
| /* Or to just after a linebreak for a multiline match */ | if (first_byte >= 0) |
| { | |
| if (first_byte_caseless) | |
| while (start_match < end_subject && md->lcc[*start_match] != first_byte) | |
| start_match++; | |
| else | |
| while (start_match < end_subject && *start_match != first_byte) | |
| start_match++; | |
| } | |
| else if (startline) | /* Or to just after a linebreak for a multiline match */ |
| { | |
| if (start_match > md->start_subject + start_offset) | else if (startline) |
| { | { |
| #ifdef SUPPORT_UTF8 | if (start_match > md->start_subject + start_offset) |
| if (utf8) | |
| { | { |
| while (start_match < end_subject && !WAS_NEWLINE(start_match)) | #ifdef SUPPORT_UTF8 |
| if (utf8) | |
| { | { |
| start_match++; | while (start_match < end_subject && !WAS_NEWLINE(start_match)) |
| while(start_match < end_subject && (*start_match & 0xc0) == 0x80) | { |
| start_match++; | start_match++; |
| while(start_match < end_subject && (*start_match & 0xc0) == 0x80) | |
| start_match++; | |
| } | |
| } | } |
| } | else |
| else | |
| #endif | #endif |
| while (start_match < end_subject && !WAS_NEWLINE(start_match)) | while (start_match < end_subject && !WAS_NEWLINE(start_match)) |
| start_match++; | start_match++; |
| /* If we have just passed a CR and the newline option is ANY or ANYCRLF, | /* If we have just passed a CR and the newline option is ANY or ANYCRLF, |
| and we are now at a LF, advance the match position by one more character. | and we are now at a LF, advance the match position by one more character. |
| */ | */ |
| if (start_match[-1] == '\r' && | if (start_match[-1] == CHAR_CR && |
| (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) && | (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) && |
| start_match < end_subject && | start_match < end_subject && |
| *start_match == '\n') | *start_match == CHAR_NL) |
| start_match++; | start_match++; |
| } | |
| } | } |
| } | |
| /* Or to a non-unique first byte after study */ | /* Or to a non-unique first byte after study */ |
| else if (start_bits != NULL) | else if (start_bits != NULL) |
| { | |
| while (start_match < end_subject) | |
| { | { |
| register unsigned int c = *start_match; | while (start_match < end_subject) |
| if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; | { |
| register unsigned int c = *start_match; | |
| if ((start_bits[c/8] & (1 << (c&7))) == 0) | |
| { | |
| start_match++; | |
| #ifdef SUPPORT_UTF8 | |
| if (utf8) | |
| while(start_match < end_subject && (*start_match & 0xc0) == 0x80) | |
| start_match++; | |
| #endif | |
| } | |
| else break; | else break; |
| } | |
| } | } |
| } | } /* Starting optimizations */ |
| /* Restore fudged end_subject */ | /* Restore fudged end_subject */ |
| end_subject = save_end_subject; | end_subject = save_end_subject; |
| #ifdef DEBUG /* Sigh. Some compilers never learn. */ | /* The following two optimizations are disabled for partial matching or if |
| printf(">>>> Match against: "); | disabling is explicitly requested. */ |
| pchars(start_match, end_subject - start_match, TRUE, md); | |
| printf("\n"); | |
| #endif | |
| /* If req_byte is set, we know that that character must appear in the subject | if ((options & PCRE_NO_START_OPTIMIZE) == 0 && !md->partial) |
| for the match to succeed. If the first character is set, req_byte must be | |
| later in the subject; otherwise the test starts at the match point. This | |
| optimization can save a huge amount of backtracking in patterns with nested | |
| unlimited repeats that aren't going to match. Writing separate code for | |
| cased/caseless versions makes it go faster, as does using an autoincrement | |
| and backing off on a match. | |
| HOWEVER: when the subject string is very, very long, searching to its end can | |
| take a long time, and give bad performance on quite ordinary patterns. This | |
| showed up when somebody was matching something like /^\d+C/ on a 32-megabyte | |
| string... so we don't do this when the string is sufficiently long. | |
| ALSO: this processing is disabled when partial matching is requested. | |
| */ | |
| if (req_byte >= 0 && | |
| end_subject - start_match < REQ_BYTE_MAX && | |
| !md->partial) | |
| { | { |
| register USPTR p = start_match + ((first_byte >= 0)? 1 : 0); | /* If the pattern was studied, a minimum subject length may be set. This is |
| a lower bound; no actual string of that length may actually match the | |
| pattern. Although the value is, strictly, in characters, we treat it as | |
| bytes to avoid spending too much time in this optimization. */ | |
| if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 && | |
| (pcre_uint32)(end_subject - start_match) < study->minlength) | |
| { | |
| rc = MATCH_NOMATCH; | |
| break; | |
| } | |
| /* If req_byte is set, we know that that character must appear in the | |
| subject for the match to succeed. If the first character is set, req_byte | |
| must be later in the subject; otherwise the test starts at the match point. | |
| This optimization can save a huge amount of backtracking in patterns with | |
| nested unlimited repeats that aren't going to match. Writing separate code | |
| for cased/caseless versions makes it go faster, as does using an | |
| autoincrement and backing off on a match. | |
| /* We don't need to repeat the search if we haven't yet reached the | HOWEVER: when the subject string is very, very long, searching to its end |
| place we found it at last time. */ | can take a long time, and give bad performance on quite ordinary patterns. |
| This showed up when somebody was matching something like /^\d+C/ on a | |
| 32-megabyte string... so we don't do this when the string is sufficiently | |
| long. */ | |
| if (p > req_byte_ptr) | if (req_byte >= 0 && end_subject - start_match < REQ_BYTE_MAX) |
| { | { |
| if (req_byte_caseless) | register USPTR p = start_match + ((first_byte >= 0)? 1 : 0); |
| /* We don't need to repeat the search if we haven't yet reached the | |
| place we found it at last time. */ | |
| if (p > req_byte_ptr) | |
| { | { |
| while (p < end_subject) | if (req_byte_caseless) |
| { | { |
| register int pp = *p++; | while (p < end_subject) |
| if (pp == req_byte || pp == req_byte2) { p--; break; } | { |
| register int pp = *p++; | |
| if (pp == req_byte || pp == req_byte2) { p--; break; } | |
| } | |
| } | } |
| } | else |
| else | |
| { | |
| while (p < end_subject) | |
| { | { |
| if (*p++ == req_byte) { p--; break; } | while (p < end_subject) |
| { | |
| if (*p++ == req_byte) { p--; break; } | |
| } | |
| } | } |
| } | |
| /* If we can't find the required character, break the matching loop, | /* If we can't find the required character, break the matching loop, |
| forcing a match failure. */ | forcing a match failure. */ |
| if (p >= end_subject) | if (p >= end_subject) |
| { | { |
| rc = MATCH_NOMATCH; | rc = MATCH_NOMATCH; |
| break; | break; |
| } | } |
| /* If we have found the required character, save the point where we | /* If we have found the required character, save the point where we |
| found it, so that we don't search again next time round the loop if | found it, so that we don't search again next time round the loop if |
| the start hasn't passed this character yet. */ | the start hasn't passed this character yet. */ |
| req_byte_ptr = p; | req_byte_ptr = p; |
| } | |
| } | } |
| } | } |
| /* OK, we can now run the match. */ | #ifdef PCRE_DEBUG /* Sigh. Some compilers never learn. */ |
| printf(">>>> Match against: "); | |
| pchars(start_match, end_subject - start_match, TRUE, md); | |
| printf("\n"); | |
| #endif | |
| /* OK, we can now run the match. If "hitend" is set afterwards, remember the | |
| first starting point for which a partial match was found. */ | |
| md->start_match_ptr = start_match; | md->start_match_ptr = start_match; |
| md->start_used_ptr = start_match; | |
| md->match_call_count = 0; | md->match_call_count = 0; |
| rc = match(start_match, md->start_code, start_match, 2, md, ims, NULL, 0, 0); | rc = match(start_match, md->start_code, start_match, NULL, 2, md, ims, NULL, |
| 0, 0); | |
| if (md->hitend && start_partial == NULL) start_partial = md->start_used_ptr; | |
| switch(rc) | switch(rc) |
| { | { |
| /* SKIP passes back the next starting point explicitly, but if it is the | |
| same as the match we have just done, treat it as NOMATCH. */ | |
| case MATCH_SKIP: | |
| if (md->start_match_ptr != start_match) | |
| { | |
| new_start_match = md->start_match_ptr; | |
| break; | |
| } | |
| /* Fall through */ | |
| /* If MATCH_SKIP_ARG reaches this level it means that a MARK that matched | |
| the SKIP's arg was not found. We also treat this as NOMATCH. */ | |
| case MATCH_SKIP_ARG: | |
| /* Fall through */ | |
| /* NOMATCH and PRUNE advance by one character. THEN at this level acts | /* NOMATCH and PRUNE advance by one character. THEN at this level acts |
| exactly like PRUNE. */ | exactly like PRUNE. */ |
| Line 4861 for(;;) | Line 6134 for(;;) |
| #endif | #endif |
| break; | break; |
| /* SKIP passes back the next starting point explicitly. */ | |
| case MATCH_SKIP: | |
| new_start_match = md->start_match_ptr; | |
| break; | |
| /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */ | /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */ |
| case MATCH_COMMIT: | case MATCH_COMMIT: |
| rc = MATCH_NOMATCH; | rc = MATCH_NOMATCH; |
| goto ENDLOOP; | goto ENDLOOP; |
| /* Any other return is some kind of error. */ | /* Any other return is either a match, or some kind of error. */ |
| default: | default: |
| goto ENDLOOP; | goto ENDLOOP; |
| Line 4903 for(;;) | Line 6170 for(;;) |
| not contain any explicit matches for \r or \n, and the newline option is CRLF | not contain any explicit matches for \r or \n, and the newline option is CRLF |
| or ANY or ANYCRLF, advance the match position by one more character. */ | or ANY or ANYCRLF, advance the match position by one more character. */ |
| if (start_match[-1] == '\r' && | if (start_match[-1] == CHAR_CR && |
| start_match < end_subject && | start_match < end_subject && |
| *start_match == '\n' && | *start_match == CHAR_NL && |
| (re->flags & PCRE_HASCRORLF) == 0 && | (re->flags & PCRE_HASCRORLF) == 0 && |
| (md->nltype == NLTYPE_ANY || | (md->nltype == NLTYPE_ANY || |
| md->nltype == NLTYPE_ANYCRLF || | md->nltype == NLTYPE_ANYCRLF || |
| md->nllen == 2)) | md->nllen == 2)) |
| start_match++; | start_match++; |
| } /* End of for(;;) "bumpalong" loop */ | md->mark = NULL; /* Reset for start of next match attempt */ |
| } /* End of for(;;) "bumpalong" loop */ | |
| /* ==========================================================================*/ | /* ==========================================================================*/ |
| Line 4936 capturing parentheses than vector slots. | Line 6204 capturing parentheses than vector slots. |
| ENDLOOP: | ENDLOOP: |
| if (rc == MATCH_MATCH) | if (rc == MATCH_MATCH || rc == MATCH_ACCEPT) |
| { | { |
| if (using_temporary_offsets) | if (using_temporary_offsets) |
| { | { |
| Line 4962 if (rc == MATCH_MATCH) | Line 6230 if (rc == MATCH_MATCH) |
| if (offsetcount < 2) rc = 0; else | if (offsetcount < 2) rc = 0; else |
| { | { |
| offsets[0] = md->start_match_ptr - md->start_subject; | offsets[0] = (int)(md->start_match_ptr - md->start_subject); |
| offsets[1] = md->end_match_ptr - md->start_subject; | offsets[1] = (int)(md->end_match_ptr - md->start_subject); |
| } | } |
| DPRINTF((">>>> returning %d\n", rc)); | DPRINTF((">>>> returning %d\n", rc)); |
| return rc; | goto RETURN_MARK; |
| } | } |
| /* Control gets here if there has been an error, or if the overall match | /* Control gets here if there has been an error, or if the overall match |
| Line 4979 if (using_temporary_offsets) | Line 6247 if (using_temporary_offsets) |
| (pcre_free)(md->offset_vector); | (pcre_free)(md->offset_vector); |
| } | } |
| if (rc != MATCH_NOMATCH) | /* For anything other than nomatch or partial match, just return the code. */ |
| if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL) | |
| { | { |
| DPRINTF((">>>> error: returning %d\n", rc)); | DPRINTF((">>>> error: returning %d\n", rc)); |
| return rc; | return rc; |
| } | } |
| else if (md->partial && md->hitend) | |
| /* Handle partial matches - disable any mark data */ | |
| if (start_partial != NULL) | |
| { | { |
| DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n")); | DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n")); |
| return PCRE_ERROR_PARTIAL; | md->mark = NULL; |
| if (offsetcount > 1) | |
| { | |
| offsets[0] = (int)(start_partial - (USPTR)subject); | |
| offsets[1] = (int)(end_subject - (USPTR)subject); | |
| } | |
| rc = PCRE_ERROR_PARTIAL; | |
| } | } |
| /* This is the classic nomatch case */ | |
| else | else |
| { | { |
| DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n")); | DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n")); |
| return PCRE_ERROR_NOMATCH; | rc = PCRE_ERROR_NOMATCH; |
| } | } |
| /* Return the MARK data if it has been requested. */ | |
| RETURN_MARK: | |
| if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) | |
| *(extra_data->mark) = (unsigned char *)(md->mark); | |
| return rc; | |
| } | } |
| /* End of pcre_exec.c */ | /* End of pcre_exec.c */ |