forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			7537 lines
		
	
	
		
			230 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			7537 lines
		
	
	
		
			230 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*************************************************
							 | 
						||
| 
								 | 
							
								*      Perl-Compatible Regular Expressions       *
							 | 
						||
| 
								 | 
							
								*************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* PCRE is a library of functions to support regular expressions whose syntax
							 | 
						||
| 
								 | 
							
								and semantics are as close as possible to those of the Perl 5 language.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                       Written by Philip Hazel
							 | 
						||
| 
								 | 
							
								     Original API code Copyright (c) 1997-2012 University of Cambridge
							 | 
						||
| 
								 | 
							
								          New API code Copyright (c) 2015-2022 University of Cambridge
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								-----------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								Redistribution and use in source and binary forms, with or without
							 | 
						||
| 
								 | 
							
								modification, are permitted provided that the following conditions are met:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * Redistributions of source code must retain the above copyright notice,
							 | 
						||
| 
								 | 
							
								      this list of conditions and the following disclaimer.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * Redistributions in binary form must reproduce the above copyright
							 | 
						||
| 
								 | 
							
								      notice, this list of conditions and the following disclaimer in the
							 | 
						||
| 
								 | 
							
								      documentation and/or other materials provided with the distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    * Neither the name of the University of Cambridge nor the names of its
							 | 
						||
| 
								 | 
							
								      contributors may be used to endorse or promote products derived from
							 | 
						||
| 
								 | 
							
								      this software without specific prior written permission.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
							 | 
						||
| 
								 | 
							
								AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
							 | 
						||
| 
								 | 
							
								IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
							 | 
						||
| 
								 | 
							
								ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
							 | 
						||
| 
								 | 
							
								LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
							 | 
						||
| 
								 | 
							
								CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
							 | 
						||
| 
								 | 
							
								SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
							 | 
						||
| 
								 | 
							
								INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
							 | 
						||
| 
								 | 
							
								CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
							 | 
						||
| 
								 | 
							
								ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
							 | 
						||
| 
								 | 
							
								POSSIBILITY OF SUCH DAMAGE.
							 | 
						||
| 
								 | 
							
								-----------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef HAVE_CONFIG_H
							 | 
						||
| 
								 | 
							
								#include "config.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* These defines enable debugging code */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* #define DEBUG_FRAMES_DISPLAY */
							 | 
						||
| 
								 | 
							
								/* #define DEBUG_SHOW_OPS */
							 | 
						||
| 
								 | 
							
								/* #define DEBUG_SHOW_RMATCH */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DEBUG_FRAMES_DISPLAY
							 | 
						||
| 
								 | 
							
								#include <stdarg.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* These defines identify the name of the block containing "static"
							 | 
						||
| 
								 | 
							
								information, and fields within it. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define NLBLOCK mb              /* Block containing newline information */
							 | 
						||
| 
								 | 
							
								#define PSSTART start_subject   /* Field containing processed string start */
							 | 
						||
| 
								 | 
							
								#define PSEND   end_subject     /* Field containing processed string end */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "pcre2_internal.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define RECURSE_UNSET 0xffffffffu  /* Bigger than max group number */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Masks for identifying the public options that are permitted at match time. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define PUBLIC_MATCH_OPTIONS \
							 | 
						||
| 
								 | 
							
								  (PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
							 | 
						||
| 
								 | 
							
								   PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \
							 | 
						||
| 
								 | 
							
								   PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT|PCRE2_COPY_MATCHED_SUBJECT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define PUBLIC_JIT_MATCH_OPTIONS \
							 | 
						||
| 
								 | 
							
								   (PCRE2_NO_UTF_CHECK|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY|\
							 | 
						||
| 
								 | 
							
								    PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_SOFT|PCRE2_PARTIAL_HARD|\
							 | 
						||
| 
								 | 
							
								    PCRE2_COPY_MATCHED_SUBJECT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Non-error returns from and within the match() function. Error returns are
							 | 
						||
| 
								 | 
							
								externally defined PCRE2_ERROR_xxx codes, which are all negative. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define MATCH_MATCH        1
							 | 
						||
| 
								 | 
							
								#define MATCH_NOMATCH      0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Special internal returns used in the match() function. Make them
							 | 
						||
| 
								 | 
							
								sufficiently negative to avoid the external error codes. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define MATCH_ACCEPT       (-999)
							 | 
						||
| 
								 | 
							
								#define MATCH_KETRPOS      (-998)
							 | 
						||
| 
								 | 
							
								/* The next 5 must be kept together and in sequence so that a test that checks
							 | 
						||
| 
								 | 
							
								for any one of them can use a range. */
							 | 
						||
| 
								 | 
							
								#define MATCH_COMMIT       (-997)
							 | 
						||
| 
								 | 
							
								#define MATCH_PRUNE        (-996)
							 | 
						||
| 
								 | 
							
								#define MATCH_SKIP         (-995)
							 | 
						||
| 
								 | 
							
								#define MATCH_SKIP_ARG     (-994)
							 | 
						||
| 
								 | 
							
								#define MATCH_THEN         (-993)
							 | 
						||
| 
								 | 
							
								#define MATCH_BACKTRACK_MAX MATCH_THEN
							 | 
						||
| 
								 | 
							
								#define MATCH_BACKTRACK_MIN MATCH_COMMIT
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Group frame type values. Zero means the frame is not a group frame. The
							 | 
						||
| 
								 | 
							
								lower 16 bits are used for data (e.g. the capture number). Group frames are
							 | 
						||
| 
								 | 
							
								used for most groups so that information about the start is easily available at
							 | 
						||
| 
								 | 
							
								the end without having to scan back through intermediate frames (backtrack
							 | 
						||
| 
								 | 
							
								points). */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define GF_CAPTURE     0x00010000u
							 | 
						||
| 
								 | 
							
								#define GF_NOCAPTURE   0x00020000u
							 | 
						||
| 
								 | 
							
								#define GF_CONDASSERT  0x00030000u
							 | 
						||
| 
								 | 
							
								#define GF_RECURSE     0x00040000u
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Masks for the identity and data parts of the group frame type. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define GF_IDMASK(a)   ((a) & 0xffff0000u)
							 | 
						||
| 
								 | 
							
								#define GF_DATAMASK(a) ((a) & 0x0000ffffu)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Repetition types */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								enum { REPTYPE_MIN, REPTYPE_MAX, REPTYPE_POS };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Min and max values for the common repeats; a maximum of UINT32_MAX =>
							 | 
						||
| 
								 | 
							
								infinity. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static const uint32_t rep_min[] = {
							 | 
						||
| 
								 | 
							
								  0, 0,       /* * and *? */
							 | 
						||
| 
								 | 
							
								  1, 1,       /* + and +? */
							 | 
						||
| 
								 | 
							
								  0, 0,       /* ? and ?? */
							 | 
						||
| 
								 | 
							
								  0, 0,       /* dummy placefillers for OP_CR[MIN]RANGE */
							 | 
						||
| 
								 | 
							
								  0, 1, 0 };  /* OP_CRPOS{STAR, PLUS, QUERY} */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static const uint32_t rep_max[] = {
							 | 
						||
| 
								 | 
							
								  UINT32_MAX, UINT32_MAX,      /* * and *? */
							 | 
						||
| 
								 | 
							
								  UINT32_MAX, UINT32_MAX,      /* + and +? */
							 | 
						||
| 
								 | 
							
								  1, 1,                        /* ? and ?? */
							 | 
						||
| 
								 | 
							
								  0, 0,                        /* dummy placefillers for OP_CR[MIN]RANGE */
							 | 
						||
| 
								 | 
							
								  UINT32_MAX, UINT32_MAX, 1 }; /* OP_CRPOS{STAR, PLUS, QUERY} */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Repetition types - must include OP_CRPOSRANGE (not needed above) */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static const uint32_t rep_typ[] = {
							 | 
						||
| 
								 | 
							
								  REPTYPE_MAX, REPTYPE_MIN,    /* * and *? */
							 | 
						||
| 
								 | 
							
								  REPTYPE_MAX, REPTYPE_MIN,    /* + and +? */
							 | 
						||
| 
								 | 
							
								  REPTYPE_MAX, REPTYPE_MIN,    /* ? and ?? */
							 | 
						||
| 
								 | 
							
								  REPTYPE_MAX, REPTYPE_MIN,    /* OP_CRRANGE and OP_CRMINRANGE */
							 | 
						||
| 
								 | 
							
								  REPTYPE_POS, REPTYPE_POS,    /* OP_CRPOSSTAR, OP_CRPOSPLUS */
							 | 
						||
| 
								 | 
							
								  REPTYPE_POS, REPTYPE_POS };  /* OP_CRPOSQUERY, OP_CRPOSRANGE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Numbers for RMATCH calls at backtracking points. When these lists are
							 | 
						||
| 
								 | 
							
								changed, the code at RETURN_SWITCH below must be updated in sync.  */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								enum { RM1=1, RM2,  RM3,  RM4,  RM5,  RM6,  RM7,  RM8,  RM9,  RM10,
							 | 
						||
| 
								 | 
							
								       RM11,  RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20,
							 | 
						||
| 
								 | 
							
								       RM21,  RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,
							 | 
						||
| 
								 | 
							
								       RM31,  RM32, RM33, RM34, RM35, RM36 };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_WIDE_CHARS
							 | 
						||
| 
								 | 
							
								enum { RM100=100, RM101 };
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								enum { RM200=200, RM201, RM202, RM203, RM204, RM205, RM206, RM207,
							 | 
						||
| 
								 | 
							
								       RM208,     RM209, RM210, RM211, RM212, RM213, RM214, RM215,
							 | 
						||
| 
								 | 
							
								       RM216,     RM217, RM218, RM219, RM220, RM221, RM222, RM223,
							 | 
						||
| 
								 | 
							
								       RM224,     RM225 };
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Define short names for general fields in the current backtrack frame, which
							 | 
						||
| 
								 | 
							
								is always pointed to by the F variable. Occasional references to fields in
							 | 
						||
| 
								 | 
							
								other frames are written out explicitly. There are also some fields in the
							 | 
						||
| 
								 | 
							
								current frame whose names start with "temp" that are used for short-term,
							 | 
						||
| 
								 | 
							
								localised backtracking memory. These are #defined with Lxxx names at the point
							 | 
						||
| 
								 | 
							
								of use and undefined afterwards. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Fback_frame        F->back_frame
							 | 
						||
| 
								 | 
							
								#define Fcapture_last      F->capture_last
							 | 
						||
| 
								 | 
							
								#define Fcurrent_recurse   F->current_recurse
							 | 
						||
| 
								 | 
							
								#define Fecode             F->ecode
							 | 
						||
| 
								 | 
							
								#define Feptr              F->eptr
							 | 
						||
| 
								 | 
							
								#define Fgroup_frame_type  F->group_frame_type
							 | 
						||
| 
								 | 
							
								#define Flast_group_offset F->last_group_offset
							 | 
						||
| 
								 | 
							
								#define Flength            F->length
							 | 
						||
| 
								 | 
							
								#define Fmark              F->mark
							 | 
						||
| 
								 | 
							
								#define Frdepth            F->rdepth
							 | 
						||
| 
								 | 
							
								#define Fstart_match       F->start_match
							 | 
						||
| 
								 | 
							
								#define Foffset_top        F->offset_top
							 | 
						||
| 
								 | 
							
								#define Foccu              F->occu
							 | 
						||
| 
								 | 
							
								#define Fop                F->op
							 | 
						||
| 
								 | 
							
								#define Fovector           F->ovector
							 | 
						||
| 
								 | 
							
								#define Freturn_id         F->return_id
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DEBUG_FRAMES_DISPLAY
							 | 
						||
| 
								 | 
							
								/*************************************************
							 | 
						||
| 
								 | 
							
								*      Display current frames and contents       *
							 | 
						||
| 
								 | 
							
								*************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* This debugging function displays the current set of frames and their
							 | 
						||
| 
								 | 
							
								contents. It is not called automatically from anywhere, the intention being
							 | 
						||
| 
								 | 
							
								that calls can be inserted where necessary when debugging frame-related
							 | 
						||
| 
								 | 
							
								problems.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Arguments:
							 | 
						||
| 
								 | 
							
								  f           the file to write to
							 | 
						||
| 
								 | 
							
								  F           the current top frame
							 | 
						||
| 
								 | 
							
								  P           a previous frame of interest
							 | 
						||
| 
								 | 
							
								  frame_size  the frame size
							 | 
						||
| 
								 | 
							
								  mb          points to the match block
							 | 
						||
| 
								 | 
							
								  s           identification text
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Returns:    nothing
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								display_frames(FILE *f, heapframe *F, heapframe *P, PCRE2_SIZE frame_size,
							 | 
						||
| 
								 | 
							
								  match_block *mb, const char *s, ...)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								uint32_t i;
							 | 
						||
| 
								 | 
							
								heapframe *Q;
							 | 
						||
| 
								 | 
							
								va_list ap;
							 | 
						||
| 
								 | 
							
								va_start(ap, s);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fprintf(f, "FRAMES ");
							 | 
						||
| 
								 | 
							
								vfprintf(f, s, ap);
							 | 
						||
| 
								 | 
							
								va_end(ap);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (P != NULL) fprintf(f, " P=%lu",
							 | 
						||
| 
								 | 
							
								  ((char *)P - (char *)(mb->match_frames))/frame_size);
							 | 
						||
| 
								 | 
							
								fprintf(f, "\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								for (i = 0, Q = mb->match_frames;
							 | 
						||
| 
								 | 
							
								     Q <= F;
							 | 
						||
| 
								 | 
							
								     i++, Q = (heapframe *)((char *)Q + frame_size))
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  fprintf(f, "Frame %d type=%x subj=%lu code=%d back=%lu id=%d",
							 | 
						||
| 
								 | 
							
								    i, Q->group_frame_type, Q->eptr - mb->start_subject, *(Q->ecode),
							 | 
						||
| 
								 | 
							
								    Q->back_frame, Q->return_id);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (Q->last_group_offset == PCRE2_UNSET)
							 | 
						||
| 
								 | 
							
								    fprintf(f, " lgoffset=unset\n");
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    fprintf(f, " lgoffset=%lu\n",  Q->last_group_offset/frame_size);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*************************************************
							 | 
						||
| 
								 | 
							
								*                Process a callout               *
							 | 
						||
| 
								 | 
							
								*************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* This function is called for all callouts, whether "standalone" or at the
							 | 
						||
| 
								 | 
							
								start of a conditional group. Feptr will be pointing to either OP_CALLOUT or
							 | 
						||
| 
								 | 
							
								OP_CALLOUT_STR. A callout block is allocated in pcre2_match() and initialized
							 | 
						||
| 
								 | 
							
								with fixed values.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Arguments:
							 | 
						||
| 
								 | 
							
								  F          points to the current backtracking frame
							 | 
						||
| 
								 | 
							
								  mb         points to the match block
							 | 
						||
| 
								 | 
							
								  lengthptr  where to return the length of the callout item
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Returns:     the return from the callout
							 | 
						||
| 
								 | 
							
								             or 0 if no callout function exists
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int
							 | 
						||
| 
								 | 
							
								do_callout(heapframe *F, match_block *mb, PCRE2_SIZE *lengthptr)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								int rc;
							 | 
						||
| 
								 | 
							
								PCRE2_SIZE save0, save1;
							 | 
						||
| 
								 | 
							
								PCRE2_SIZE *callout_ovector;
							 | 
						||
| 
								 | 
							
								pcre2_callout_block *cb;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*lengthptr = (*Fecode == OP_CALLOUT)?
							 | 
						||
| 
								 | 
							
								  PRIV(OP_lengths)[OP_CALLOUT] : GET(Fecode, 1 + 2*LINK_SIZE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (mb->callout == NULL) return 0;   /* No callout function provided */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* The original matching code (pre 10.30) worked directly with the ovector
							 | 
						||
| 
								 | 
							
								passed by the user, and this was passed to callouts. Now that the working
							 | 
						||
| 
								 | 
							
								ovector is in the backtracking frame, it no longer needs to reserve space for
							 | 
						||
| 
								 | 
							
								the overall match offsets (which would waste space in the frame). For backward
							 | 
						||
| 
								 | 
							
								compatibility, however, we pass capture_top and offset_vector to the callout as
							 | 
						||
| 
								 | 
							
								if for the extended ovector, and we ensure that the first two slots are unset
							 | 
						||
| 
								 | 
							
								by preserving and restoring their current contents. Picky compilers complain if
							 | 
						||
| 
								 | 
							
								references such as Fovector[-2] are use directly, so we set up a separate
							 | 
						||
| 
								 | 
							
								pointer. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								callout_ovector = (PCRE2_SIZE *)(Fovector) - 2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* The cb->version, cb->subject, cb->subject_length, and cb->start_match fields
							 | 
						||
| 
								 | 
							
								are set externally. The first 3 never change; the last is updated for each
							 | 
						||
| 
								 | 
							
								bumpalong. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								cb = mb->cb;
							 | 
						||
| 
								 | 
							
								cb->capture_top      = (uint32_t)Foffset_top/2 + 1;
							 | 
						||
| 
								 | 
							
								cb->capture_last     = Fcapture_last;
							 | 
						||
| 
								 | 
							
								cb->offset_vector    = callout_ovector;
							 | 
						||
| 
								 | 
							
								cb->mark             = mb->nomatch_mark;
							 | 
						||
| 
								 | 
							
								cb->current_position = (PCRE2_SIZE)(Feptr - mb->start_subject);
							 | 
						||
| 
								 | 
							
								cb->pattern_position = GET(Fecode, 1);
							 | 
						||
| 
								 | 
							
								cb->next_item_length = GET(Fecode, 1 + LINK_SIZE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (*Fecode == OP_CALLOUT)  /* Numerical callout */
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  cb->callout_number = Fecode[1 + 2*LINK_SIZE];
							 | 
						||
| 
								 | 
							
								  cb->callout_string_offset = 0;
							 | 
						||
| 
								 | 
							
								  cb->callout_string = NULL;
							 | 
						||
| 
								 | 
							
								  cb->callout_string_length = 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								else  /* String callout */
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  cb->callout_number = 0;
							 | 
						||
| 
								 | 
							
								  cb->callout_string_offset = GET(Fecode, 1 + 3*LINK_SIZE);
							 | 
						||
| 
								 | 
							
								  cb->callout_string = Fecode + (1 + 4*LINK_SIZE) + 1;
							 | 
						||
| 
								 | 
							
								  cb->callout_string_length =
							 | 
						||
| 
								 | 
							
								    *lengthptr - (1 + 4*LINK_SIZE) - 2;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								save0 = callout_ovector[0];
							 | 
						||
| 
								 | 
							
								save1 = callout_ovector[1];
							 | 
						||
| 
								 | 
							
								callout_ovector[0] = callout_ovector[1] = PCRE2_UNSET;
							 | 
						||
| 
								 | 
							
								rc = mb->callout(cb, mb->callout_data);
							 | 
						||
| 
								 | 
							
								callout_ovector[0] = save0;
							 | 
						||
| 
								 | 
							
								callout_ovector[1] = save1;
							 | 
						||
| 
								 | 
							
								cb->callout_flags = 0;
							 | 
						||
| 
								 | 
							
								return rc;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*************************************************
							 | 
						||
| 
								 | 
							
								*          Match a back-reference                *
							 | 
						||
| 
								 | 
							
								*************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* This function is called only when it is known that the offset lies within
							 | 
						||
| 
								 | 
							
								the offsets that have so far been used in the match. Note that in caseless
							 | 
						||
| 
								 | 
							
								UTF-8 mode, the number of subject bytes matched may be different to the number
							 | 
						||
| 
								 | 
							
								of reference bytes. (In theory this could also happen in UTF-16 mode, but it
							 | 
						||
| 
								 | 
							
								seems unlikely.)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Arguments:
							 | 
						||
| 
								 | 
							
								  offset      index into the offset vector
							 | 
						||
| 
								 | 
							
								  caseless    TRUE if caseless
							 | 
						||
| 
								 | 
							
								  F           the current backtracking frame pointer
							 | 
						||
| 
								 | 
							
								  mb          points to match block
							 | 
						||
| 
								 | 
							
								  lengthptr   pointer for returning the length matched
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Returns:      = 0 sucessful match; number of code units matched is set
							 | 
						||
| 
								 | 
							
								              < 0 no match
							 | 
						||
| 
								 | 
							
								              > 0 partial match
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int
							 | 
						||
| 
								 | 
							
								match_ref(PCRE2_SIZE offset, BOOL caseless, heapframe *F, match_block *mb,
							 | 
						||
| 
								 | 
							
								  PCRE2_SIZE *lengthptr)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR p;
							 | 
						||
| 
								 | 
							
								PCRE2_SIZE length;
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR eptr;
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR eptr_start;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Deal with an unset group. The default is no match, but there is an option to
							 | 
						||
| 
								 | 
							
								match an empty string. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (offset >= Foffset_top || Fovector[offset] == PCRE2_UNSET)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  if ((mb->poptions & PCRE2_MATCH_UNSET_BACKREF) != 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    *lengthptr = 0;
							 | 
						||
| 
								 | 
							
								    return 0;      /* Match */
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else return -1;  /* No match */
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Separate the caseless and UTF cases for speed. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								eptr = eptr_start = Feptr;
							 | 
						||
| 
								 | 
							
								p = mb->start_subject + Fovector[offset];
							 | 
						||
| 
								 | 
							
								length = Fovector[offset+1] - Fovector[offset];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (caseless)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								#if defined SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								  BOOL utf = (mb->poptions & PCRE2_UTF) != 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (utf || (mb->poptions & PCRE2_UCP) != 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    PCRE2_SPTR endptr = p + length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Match characters up to the end of the reference. NOTE: the number of
							 | 
						||
| 
								 | 
							
								    code units matched may differ, because in UTF-8 there are some characters
							 | 
						||
| 
								 | 
							
								    whose upper and lower case codes have different numbers of bytes. For
							 | 
						||
| 
								 | 
							
								    example, U+023A (2 bytes in UTF-8) is the upper case version of U+2C65 (3
							 | 
						||
| 
								 | 
							
								    bytes in UTF-8); a sequence of 3 of the former uses 6 bytes, as does a
							 | 
						||
| 
								 | 
							
								    sequence of two of the latter. It is important, therefore, to check the
							 | 
						||
| 
								 | 
							
								    length along the reference, not along the subject (earlier code did this
							 | 
						||
| 
								 | 
							
								    wrong). UCP without uses Unicode properties but without UTF encoding. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while (p < endptr)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      uint32_t c, d;
							 | 
						||
| 
								 | 
							
								      const ucd_record *ur;
							 | 
						||
| 
								 | 
							
								      if (eptr >= mb->end_subject) return 1;   /* Partial match */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (utf)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        GETCHARINC(c, eptr);
							 | 
						||
| 
								 | 
							
								        GETCHARINC(d, p);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        c = *eptr++;
							 | 
						||
| 
								 | 
							
								        d = *p++;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      ur = GET_UCD(d);
							 | 
						||
| 
								 | 
							
								      if (c != d && c != (uint32_t)((int)d + ur->other_case))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        const uint32_t *pp = PRIV(ucd_caseless_sets) + ur->caseset;
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (c < *pp) return -1;  /* No match */
							 | 
						||
| 
								 | 
							
								          if (c == *pp++) break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Not in UTF or UCP mode */
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    for (; length > 0; length--)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      uint32_t cc, cp;
							 | 
						||
| 
								 | 
							
								      if (eptr >= mb->end_subject) return 1;   /* Partial match */
							 | 
						||
| 
								 | 
							
								      cc = UCHAR21TEST(eptr);
							 | 
						||
| 
								 | 
							
								      cp = UCHAR21TEST(p);
							 | 
						||
| 
								 | 
							
								      if (TABLE_GET(cp, mb->lcc, cp) != TABLE_GET(cc, mb->lcc, cc))
							 | 
						||
| 
								 | 
							
								        return -1;  /* No match */
							 | 
						||
| 
								 | 
							
								      p++;
							 | 
						||
| 
								 | 
							
								      eptr++;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* In the caseful case, we can just compare the code units, whether or not we
							 | 
						||
| 
								 | 
							
								are in UTF and/or UCP mode. When partial matching, we have to do this unit by
							 | 
						||
| 
								 | 
							
								unit. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  if (mb->partial != 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    for (; length > 0; length--)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (eptr >= mb->end_subject) return 1;   /* Partial match */
							 | 
						||
| 
								 | 
							
								      if (UCHAR21INCTEST(p) != UCHAR21INCTEST(eptr)) return -1;  /* No match */
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Not partial matching */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    if ((PCRE2_SIZE)(mb->end_subject - eptr) < length) return 1; /* Partial */
							 | 
						||
| 
								 | 
							
								    if (memcmp(p, eptr, CU2BYTES(length)) != 0) return -1;  /* No match */
							 | 
						||
| 
								 | 
							
								    eptr += length;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*lengthptr = eptr - eptr_start;
							 | 
						||
| 
								 | 
							
								return 0;  /* Match */
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/******************************************************************************
							 | 
						||
| 
								 | 
							
								*******************************************************************************
							 | 
						||
| 
								 | 
							
								                   "Recursion" in the match() function
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The original match() function was highly recursive, but this proved to be the
							 | 
						||
| 
								 | 
							
								source of a number of problems over the years, mostly because of the relatively
							 | 
						||
| 
								 | 
							
								small system stacks that are commonly found. As new features were added to
							 | 
						||
| 
								 | 
							
								patterns, various kludges were invented to reduce the amount of stack used,
							 | 
						||
| 
								 | 
							
								making the code hard to understand in places.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A version did exist that used individual frames on the heap instead of calling
							 | 
						||
| 
								 | 
							
								match() recursively, but this ran substantially slower. The current version is
							 | 
						||
| 
								 | 
							
								a refactoring that uses a vector of frames to remember backtracking points.
							 | 
						||
| 
								 | 
							
								This runs no slower, and possibly even a bit faster than the original recursive
							 | 
						||
| 
								 | 
							
								implementation. An initial vector of size START_FRAMES_SIZE (enough for maybe
							 | 
						||
| 
								 | 
							
								50 frames) is allocated on the system stack. If this is not big enough, the
							 | 
						||
| 
								 | 
							
								heap is used for a larger vector.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*******************************************************************************
							 | 
						||
| 
								 | 
							
								******************************************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*************************************************
							 | 
						||
| 
								 | 
							
								*       Macros for the match() function          *
							 | 
						||
| 
								 | 
							
								*************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* These macros pack up tests that are used for partial matching several times
							 | 
						||
| 
								 | 
							
								in the code. The second one is used when we already know we are past the end of
							 | 
						||
| 
								 | 
							
								the subject. We set the "hit end" flag if the pointer is at the end of the
							 | 
						||
| 
								 | 
							
								subject and either (a) the pointer is past the earliest inspected character
							 | 
						||
| 
								 | 
							
								(i.e. something has been matched, even if not part of the actual matched
							 | 
						||
| 
								 | 
							
								string), or (b) the pattern contains a lookbehind. These are the conditions for
							 | 
						||
| 
								 | 
							
								which adding more characters may allow the current match to continue.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For hard partial matching, we immediately return a partial match. Otherwise,
							 | 
						||
| 
								 | 
							
								carrying on means that a complete match on the current subject will be sought.
							 | 
						||
| 
								 | 
							
								A partial match is returned only if no complete match can be found. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define CHECK_PARTIAL()\
							 | 
						||
| 
								 | 
							
								  if (Feptr >= mb->end_subject) \
							 | 
						||
| 
								 | 
							
								    { \
							 | 
						||
| 
								 | 
							
								    SCHECK_PARTIAL(); \
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define SCHECK_PARTIAL()\
							 | 
						||
| 
								 | 
							
								  if (mb->partial != 0 && \
							 | 
						||
| 
								 | 
							
								      (Feptr > mb->start_used_ptr || mb->allowemptypartial)) \
							 | 
						||
| 
								 | 
							
								    { \
							 | 
						||
| 
								 | 
							
								    mb->hitend = TRUE; \
							 | 
						||
| 
								 | 
							
								    if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* These macros are used to implement backtracking. They simulate a recursive
							 | 
						||
| 
								 | 
							
								call to the match() function by means of a local vector of frames which
							 | 
						||
| 
								 | 
							
								remember the backtracking points. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define RMATCH(ra,rb)\
							 | 
						||
| 
								 | 
							
								  {\
							 | 
						||
| 
								 | 
							
								  start_ecode = ra;\
							 | 
						||
| 
								 | 
							
								  Freturn_id = rb;\
							 | 
						||
| 
								 | 
							
								  goto MATCH_RECURSE;\
							 | 
						||
| 
								 | 
							
								  L_##rb:;\
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define RRETURN(ra)\
							 | 
						||
| 
								 | 
							
								  {\
							 | 
						||
| 
								 | 
							
								  rrc = ra;\
							 | 
						||
| 
								 | 
							
								  goto RETURN_SWITCH;\
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*************************************************
							 | 
						||
| 
								 | 
							
								*         Match from current position            *
							 | 
						||
| 
								 | 
							
								*************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* This function is called to run one match attempt at a single starting point
							 | 
						||
| 
								 | 
							
								in the subject.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Performance note: It might be tempting to extract commonly used fields from the
							 | 
						||
| 
								 | 
							
								mb structure (e.g. end_subject) into individual variables to improve
							 | 
						||
| 
								 | 
							
								performance. Tests using gcc on a SPARC disproved this; in the first case, it
							 | 
						||
| 
								 | 
							
								made performance worse.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Arguments:
							 | 
						||
| 
								 | 
							
								   start_eptr   starting character in subject
							 | 
						||
| 
								 | 
							
								   start_ecode  starting position in compiled code
							 | 
						||
| 
								 | 
							
								   ovector      pointer to the final output vector
							 | 
						||
| 
								 | 
							
								   oveccount    number of pairs in ovector
							 | 
						||
| 
								 | 
							
								   top_bracket  number of capturing parentheses in the pattern
							 | 
						||
| 
								 | 
							
								   frame_size   size of each backtracking frame
							 | 
						||
| 
								 | 
							
								   mb           pointer to "static" variables block
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Returns:        MATCH_MATCH if matched            )  these values are >= 0
							 | 
						||
| 
								 | 
							
								                MATCH_NOMATCH if failed to match  )
							 | 
						||
| 
								 | 
							
								                negative MATCH_xxx value for PRUNE, SKIP, etc
							 | 
						||
| 
								 | 
							
								                negative PCRE2_ERROR_xxx value if aborted by an error condition
							 | 
						||
| 
								 | 
							
								                (e.g. stopped by repeated call or depth limit)
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int
							 | 
						||
| 
								 | 
							
								match(PCRE2_SPTR start_eptr, PCRE2_SPTR start_ecode, PCRE2_SIZE *ovector,
							 | 
						||
| 
								 | 
							
								  uint16_t oveccount, uint16_t top_bracket, PCRE2_SIZE frame_size,
							 | 
						||
| 
								 | 
							
								  match_block *mb)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								/* Frame-handling variables */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								heapframe *F;           /* Current frame pointer */
							 | 
						||
| 
								 | 
							
								heapframe *N = NULL;    /* Temporary frame pointers */
							 | 
						||
| 
								 | 
							
								heapframe *P = NULL;
							 | 
						||
| 
								 | 
							
								heapframe *assert_accept_frame = NULL;  /* For passing back a frame with captures */
							 | 
						||
| 
								 | 
							
								PCRE2_SIZE frame_copy_size;     /* Amount to copy when creating a new frame */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Local variables that do not need to be preserved over calls to RRMATCH(). */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR bracode;     /* Temp pointer to start of group */
							 | 
						||
| 
								 | 
							
								PCRE2_SIZE offset;      /* Used for group offsets */
							 | 
						||
| 
								 | 
							
								PCRE2_SIZE length;      /* Used for various length calculations */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int rrc;                /* Return from functions & backtracking "recursions" */
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								int proptype;           /* Type of character property */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t i;             /* Used for local loops */
							 | 
						||
| 
								 | 
							
								uint32_t fc;            /* Character values */
							 | 
						||
| 
								 | 
							
								uint32_t number;        /* Used for group and other numbers */
							 | 
						||
| 
								 | 
							
								uint32_t reptype = 0;   /* Type of repetition (0 to avoid compiler warning) */
							 | 
						||
| 
								 | 
							
								uint32_t group_frame_type;  /* Specifies type for new group frames */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOL condition;         /* Used in conditional groups */
							 | 
						||
| 
								 | 
							
								BOOL cur_is_word;       /* Used in "word" tests */
							 | 
						||
| 
								 | 
							
								BOOL prev_is_word;      /* Used in "word" tests */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* UTF and UCP flags */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								BOOL utf = (mb->poptions & PCRE2_UTF) != 0;
							 | 
						||
| 
								 | 
							
								BOOL ucp = (mb->poptions & PCRE2_UCP) != 0;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								BOOL utf = FALSE;  /* Required for convenience even when no Unicode support */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* This is the length of the last part of a backtracking frame that must be
							 | 
						||
| 
								 | 
							
								copied when a new frame is created. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								frame_copy_size = frame_size - offsetof(heapframe, eptr);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Set up the first current frame at the start of the vector, and initialize
							 | 
						||
| 
								 | 
							
								fields that are not reset for new frames. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								F = mb->match_frames;
							 | 
						||
| 
								 | 
							
								Frdepth = 0;                        /* "Recursion" depth */
							 | 
						||
| 
								 | 
							
								Fcapture_last = 0;                  /* Number of most recent capture */
							 | 
						||
| 
								 | 
							
								Fcurrent_recurse = RECURSE_UNSET;   /* Not pattern recursing. */
							 | 
						||
| 
								 | 
							
								Fstart_match = Feptr = start_eptr;  /* Current data pointer and start match */
							 | 
						||
| 
								 | 
							
								Fmark = NULL;                       /* Most recent mark */
							 | 
						||
| 
								 | 
							
								Foffset_top = 0;                    /* End of captures within the frame */
							 | 
						||
| 
								 | 
							
								Flast_group_offset = PCRE2_UNSET;   /* Saved frame of most recent group */
							 | 
						||
| 
								 | 
							
								group_frame_type = 0;               /* Not a start of group frame */
							 | 
						||
| 
								 | 
							
								goto NEW_FRAME;                     /* Start processing with this frame */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Come back here when we want to create a new frame for remembering a
							 | 
						||
| 
								 | 
							
								backtracking point. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								MATCH_RECURSE:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Set up a new backtracking frame. If the vector is full, get a new one
							 | 
						||
| 
								 | 
							
								on the heap, doubling the size, but constrained by the heap limit. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								N = (heapframe *)((char *)F + frame_size);
							 | 
						||
| 
								 | 
							
								if (N >= mb->match_frames_top)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  PCRE2_SIZE newsize = mb->frame_vector_size * 2;
							 | 
						||
| 
								 | 
							
								  heapframe *new;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ((newsize / 1024) > mb->heap_limit)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    PCRE2_SIZE maxsize = ((mb->heap_limit * 1024)/frame_size) * frame_size;
							 | 
						||
| 
								 | 
							
								    if (mb->frame_vector_size >= maxsize) return PCRE2_ERROR_HEAPLIMIT;
							 | 
						||
| 
								 | 
							
								    newsize = maxsize;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  new = mb->memctl.malloc(newsize, mb->memctl.memory_data);
							 | 
						||
| 
								 | 
							
								  if (new == NULL) return PCRE2_ERROR_NOMEMORY;
							 | 
						||
| 
								 | 
							
								  memcpy(new, mb->match_frames, mb->frame_vector_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  F = (heapframe *)((char *)new + ((char *)F - (char *)mb->match_frames));
							 | 
						||
| 
								 | 
							
								  N = (heapframe *)((char *)F + frame_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mb->match_frames != mb->stack_frames)
							 | 
						||
| 
								 | 
							
								    mb->memctl.free(mb->match_frames, mb->memctl.memory_data);
							 | 
						||
| 
								 | 
							
								  mb->match_frames = new;
							 | 
						||
| 
								 | 
							
								  mb->match_frames_top = (heapframe *)((char *)mb->match_frames + newsize);
							 | 
						||
| 
								 | 
							
								  mb->frame_vector_size = newsize;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DEBUG_SHOW_RMATCH
							 | 
						||
| 
								 | 
							
								fprintf(stderr, "++ RMATCH %2d frame=%d", Freturn_id, Frdepth + 1);
							 | 
						||
| 
								 | 
							
								if (group_frame_type != 0)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  fprintf(stderr, " type=%x ", group_frame_type);
							 | 
						||
| 
								 | 
							
								  switch (GF_IDMASK(group_frame_type))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    case GF_CAPTURE:
							 | 
						||
| 
								 | 
							
								    fprintf(stderr, "capture=%d", GF_DATAMASK(group_frame_type));
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case GF_NOCAPTURE:
							 | 
						||
| 
								 | 
							
								    fprintf(stderr, "nocapture op=%d", GF_DATAMASK(group_frame_type));
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case GF_CONDASSERT:
							 | 
						||
| 
								 | 
							
								    fprintf(stderr, "condassert op=%d", GF_DATAMASK(group_frame_type));
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case GF_RECURSE:
							 | 
						||
| 
								 | 
							
								    fprintf(stderr, "recurse=%d", GF_DATAMASK(group_frame_type));
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								    fprintf(stderr, "*** unknown ***");
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								fprintf(stderr, "\n");
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Copy those fields that must be copied into the new frame, increase the
							 | 
						||
| 
								 | 
							
								"recursion" depth (i.e. the new frame's index) and then make the new frame
							 | 
						||
| 
								 | 
							
								current. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								memcpy((char *)N + offsetof(heapframe, eptr),
							 | 
						||
| 
								 | 
							
								       (char *)F + offsetof(heapframe, eptr),
							 | 
						||
| 
								 | 
							
								       frame_copy_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								N->rdepth = Frdepth + 1;
							 | 
						||
| 
								 | 
							
								F = N;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Carry on processing with a new frame. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								NEW_FRAME:
							 | 
						||
| 
								 | 
							
								Fgroup_frame_type = group_frame_type;
							 | 
						||
| 
								 | 
							
								Fecode = start_ecode;      /* Starting code pointer */
							 | 
						||
| 
								 | 
							
								Fback_frame = frame_size;  /* Default is go back one frame */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* If this is a special type of group frame, remember its offset for quick
							 | 
						||
| 
								 | 
							
								access at the end of the group. If this is a recursion, set a new current
							 | 
						||
| 
								 | 
							
								recursion value. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (group_frame_type != 0)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  Flast_group_offset = (char *)F - (char *)mb->match_frames;
							 | 
						||
| 
								 | 
							
								  if (GF_IDMASK(group_frame_type) == GF_RECURSE)
							 | 
						||
| 
								 | 
							
								    Fcurrent_recurse = GF_DATAMASK(group_frame_type);
							 | 
						||
| 
								 | 
							
								  group_frame_type = 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ========================================================================= */
							 | 
						||
| 
								 | 
							
								/* This is the main processing loop. First check that we haven't recorded too
							 | 
						||
| 
								 | 
							
								many backtracks (search tree is too large), or that we haven't exceeded the
							 | 
						||
| 
								 | 
							
								recursive depth limit (used too many backtracking frames). If not, process the
							 | 
						||
| 
								 | 
							
								opcodes. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (mb->match_call_count++ >= mb->match_limit) return PCRE2_ERROR_MATCHLIMIT;
							 | 
						||
| 
								 | 
							
								if (Frdepth >= mb->match_limit_depth) return PCRE2_ERROR_DEPTHLIMIT;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								for (;;)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								#ifdef DEBUG_SHOW_OPS
							 | 
						||
| 
								 | 
							
								fprintf(stderr, "++ op=%d\n", *Fecode);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Fop = (uint8_t)(*Fecode);  /* Cast needed for 16-bit and 32-bit modes */
							 | 
						||
| 
								 | 
							
								  switch(Fop)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Before OP_ACCEPT there may be any number of OP_CLOSE opcodes, to close
							 | 
						||
| 
								 | 
							
								    any currently open capturing brackets. Unlike reaching the end of a group,
							 | 
						||
| 
								 | 
							
								    where we know the starting frame is at the top of the chained frames, in
							 | 
						||
| 
								 | 
							
								    this case we have to search back for the relevant frame in case other types
							 | 
						||
| 
								 | 
							
								    of group that use chained frames have intervened. Multiple OP_CLOSEs always
							 | 
						||
| 
								 | 
							
								    come innermost first, which matches the chain order. We can ignore this in
							 | 
						||
| 
								 | 
							
								    a recursion, because captures are not passed out of recursions. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_CLOSE:
							 | 
						||
| 
								 | 
							
								    if (Fcurrent_recurse == RECURSE_UNSET)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      number = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								      offset = Flast_group_offset;
							 | 
						||
| 
								 | 
							
								      for(;;)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								        N = (heapframe *)((char *)mb->match_frames + offset);
							 | 
						||
| 
								 | 
							
								        P = (heapframe *)((char *)N - frame_size);
							 | 
						||
| 
								 | 
							
								        if (N->group_frame_type == (GF_CAPTURE | number)) break;
							 | 
						||
| 
								 | 
							
								        offset = P->last_group_offset;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      offset = (number << 1) - 2;
							 | 
						||
| 
								 | 
							
								      Fcapture_last = number;
							 | 
						||
| 
								 | 
							
								      Fovector[offset] = P->eptr - mb->start_subject;
							 | 
						||
| 
								 | 
							
								      Fovector[offset+1] = Feptr - mb->start_subject;
							 | 
						||
| 
								 | 
							
								      if (offset >= Foffset_top) Foffset_top = offset + 2;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Fecode += PRIV(OP_lengths)[*Fecode];
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Real or forced end of the pattern, assertion, or recursion. In an
							 | 
						||
| 
								 | 
							
								    assertion ACCEPT, update the last used pointer and remember the current
							 | 
						||
| 
								 | 
							
								    frame so that the captures and mark can be fished out of it. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_ASSERT_ACCEPT:
							 | 
						||
| 
								 | 
							
								    if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
							 | 
						||
| 
								 | 
							
								    assert_accept_frame = F;
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_ACCEPT);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If recursing, we have to find the most recent recursion. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_ACCEPT:
							 | 
						||
| 
								 | 
							
								    case OP_END:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Handle end of a recursion. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Fcurrent_recurse != RECURSE_UNSET)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      offset = Flast_group_offset;
							 | 
						||
| 
								 | 
							
								      for(;;)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								        N = (heapframe *)((char *)mb->match_frames + offset);
							 | 
						||
| 
								 | 
							
								        P = (heapframe *)((char *)N - frame_size);
							 | 
						||
| 
								 | 
							
								        if (GF_IDMASK(N->group_frame_type) == GF_RECURSE) break;
							 | 
						||
| 
								 | 
							
								        offset = P->last_group_offset;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* N is now the frame of the recursion; the previous frame is at the
							 | 
						||
| 
								 | 
							
								      OP_RECURSE position. Go back there, copying the current subject position
							 | 
						||
| 
								 | 
							
								      and mark, and the start_match position (\K might have changed it), and
							 | 
						||
| 
								 | 
							
								      then move on past the OP_RECURSE. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      P->eptr = Feptr;
							 | 
						||
| 
								 | 
							
								      P->mark = Fmark;
							 | 
						||
| 
								 | 
							
								      P->start_match = Fstart_match;
							 | 
						||
| 
								 | 
							
								      F = P;
							 | 
						||
| 
								 | 
							
								      Fecode += 1 + LINK_SIZE;
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Not a recursion. Fail for an empty string match if either PCRE2_NOTEMPTY
							 | 
						||
| 
								 | 
							
								    is set, or if PCRE2_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 (Feptr == Fstart_match &&
							 | 
						||
| 
								 | 
							
								         ((mb->moptions & PCRE2_NOTEMPTY) != 0 ||
							 | 
						||
| 
								 | 
							
								           ((mb->moptions & PCRE2_NOTEMPTY_ATSTART) != 0 &&
							 | 
						||
| 
								 | 
							
								             Fstart_match == mb->start_subject + mb->start_offset)))
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Also fail if PCRE2_ENDANCHORED is set and the end of the match is not
							 | 
						||
| 
								 | 
							
								    the end of the subject. After (*ACCEPT) we fail the entire match (at this
							 | 
						||
| 
								 | 
							
								    position) but backtrack on reaching the end of the pattern. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Feptr < mb->end_subject &&
							 | 
						||
| 
								 | 
							
								        ((mb->moptions | mb->poptions) & PCRE2_ENDANCHORED) != 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (Fop == OP_END) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      return MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* We have a successful match of the whole pattern. Record the result and
							 | 
						||
| 
								 | 
							
								    then do a direct return from the function. If there is space in the offset
							 | 
						||
| 
								 | 
							
								    vector, set any pairs that follow the highest-numbered captured string but
							 | 
						||
| 
								 | 
							
								    are less than the number of capturing groups in the pattern to PCRE2_UNSET.
							 | 
						||
| 
								 | 
							
								    It is documented that this happens. "Gaps" are set to PCRE2_UNSET
							 | 
						||
| 
								 | 
							
								    dynamically. It is only those at the end that need setting here. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mb->end_match_ptr = Feptr;           /* Record where we ended */
							 | 
						||
| 
								 | 
							
								    mb->end_offset_top = Foffset_top;    /* and how many extracts were taken */
							 | 
						||
| 
								 | 
							
								    mb->mark = Fmark;                    /* and the last success mark */
							 | 
						||
| 
								 | 
							
								    if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ovector[0] = Fstart_match - mb->start_subject;
							 | 
						||
| 
								 | 
							
								    ovector[1] = Feptr - mb->start_subject;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Set i to the smaller of the sizes of the external and frame ovectors. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    i = 2 * ((top_bracket + 1 > oveccount)? oveccount : top_bracket + 1);
							 | 
						||
| 
								 | 
							
								    memcpy(ovector + 2, Fovector, (i - 2) * sizeof(PCRE2_SIZE));
							 | 
						||
| 
								 | 
							
								    while (--i >= Foffset_top + 2) ovector[i] = PCRE2_UNSET;
							 | 
						||
| 
								 | 
							
								    return MATCH_MATCH;  /* Note: NOT RRETURN */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match any single character type except newline; have to take care with
							 | 
						||
| 
								 | 
							
								    CRLF newlines and partial matching. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_ANY:
							 | 
						||
| 
								 | 
							
								    if (IS_NEWLINE(Feptr)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    if (mb->partial != 0 &&
							 | 
						||
| 
								 | 
							
								        Feptr == mb->end_subject - 1 &&
							 | 
						||
| 
								 | 
							
								        NLBLOCK->nltype == NLTYPE_FIXED &&
							 | 
						||
| 
								 | 
							
								        NLBLOCK->nllen == 2 &&
							 | 
						||
| 
								 | 
							
								        UCHAR21TEST(Feptr) == NLBLOCK->nl[0])
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								      if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    /* Fall through */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Match any single character whatsoever. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_ALLANY:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)  /* DO NOT merge the Feptr++ here; it must */
							 | 
						||
| 
								 | 
							
								      {                            /* not be updated before SCHECK_PARTIAL. */
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Feptr++;
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								    if (utf) ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match a single code unit, even in UTF mode. This opcode really does
							 | 
						||
| 
								 | 
							
								    match any code unit, even newline. (It really should be called ANYCODEUNIT,
							 | 
						||
| 
								 | 
							
								    of course - the byte name is from pre-16 bit days.) */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_ANYBYTE:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)   /* DO NOT merge the Feptr++ here; it must */
							 | 
						||
| 
								 | 
							
								      {                             /* not be updated before SCHECK_PARTIAL. */
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Feptr++;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match a single character, casefully */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_CHAR:
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								    if (utf)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Flength = 1;
							 | 
						||
| 
								 | 
							
								      Fecode++;
							 | 
						||
| 
								 | 
							
								      GETCHARLEN(fc, Fecode, Flength);
							 | 
						||
| 
								 | 
							
								      if (Flength > (PCRE2_SIZE)(mb->end_subject - Feptr))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        CHECK_PARTIAL();             /* Not SCHECK_PARTIAL() */
							 | 
						||
| 
								 | 
							
								        RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      for (; Flength > 0; Flength--)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (*Fecode++ != UCHAR21INC(Feptr)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (mb->end_subject - Feptr < 1)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        SCHECK_PARTIAL();            /* This one can use SCHECK_PARTIAL() */
							 | 
						||
| 
								 | 
							
								        RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      if (Fecode[1] != *Feptr++) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      Fecode += 2;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match a single character, caselessly. If we are at the end of the
							 | 
						||
| 
								 | 
							
								    subject, give up immediately. We get here only when the pattern character
							 | 
						||
| 
								 | 
							
								    has at most one other case. Characters with more than two cases are coded
							 | 
						||
| 
								 | 
							
								    as OP_PROP with the pseudo-property PT_CLIST. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_CHARI:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								    if (utf)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Flength = 1;
							 | 
						||
| 
								 | 
							
								      Fecode++;
							 | 
						||
| 
								 | 
							
								      GETCHARLEN(fc, Fecode, Flength);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If the pattern character's value is < 128, we know that its other case
							 | 
						||
| 
								 | 
							
								      (if any) is also < 128 (and therefore only one code unit long in all
							 | 
						||
| 
								 | 
							
								      code-unit widths), so we can use the fast lookup table. We checked above
							 | 
						||
| 
								 | 
							
								      that there is at least one character left in the subject. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (fc < 128)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        uint32_t cc = UCHAR21(Feptr);
							 | 
						||
| 
								 | 
							
								        if (mb->lcc[fc] != TABLE_GET(cc, mb->lcc, cc)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        Fecode++;
							 | 
						||
| 
								 | 
							
								        Feptr++;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Otherwise we must pick up the subject character and use Unicode
							 | 
						||
| 
								 | 
							
								      property support to test its other case. Note that we cannot use the
							 | 
						||
| 
								 | 
							
								      value of "Flength" to check for sufficient bytes left, because the other
							 | 
						||
| 
								 | 
							
								      case of the character may have more or fewer code units. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        uint32_t dc;
							 | 
						||
| 
								 | 
							
								        GETCHARINC(dc, Feptr);
							 | 
						||
| 
								 | 
							
								        Fecode += Flength;
							 | 
						||
| 
								 | 
							
								        if (dc != fc && dc != UCD_OTHERCASE(fc)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If UCP is set without UTF we must do the same as above, but with one
							 | 
						||
| 
								 | 
							
								    character per code unit. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else if (ucp)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      uint32_t cc = UCHAR21(Feptr);
							 | 
						||
| 
								 | 
							
								      fc = Fecode[1];
							 | 
						||
| 
								 | 
							
								      if (fc < 128)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (mb->lcc[fc] != TABLE_GET(cc, mb->lcc, cc)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (cc != fc && cc != UCD_OTHERCASE(fc)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      Feptr++;
							 | 
						||
| 
								 | 
							
								      Fecode += 2;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								#endif   /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Not UTF or UCP mode; use the table for characters < 256. */
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (TABLE_GET(Fecode[1], mb->lcc, Fecode[1])
							 | 
						||
| 
								 | 
							
								          != TABLE_GET(*Feptr, mb->lcc, *Feptr)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      Feptr++;
							 | 
						||
| 
								 | 
							
								      Fecode += 2;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match not a single character. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOT:
							 | 
						||
| 
								 | 
							
								    case OP_NOTI:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								    if (utf)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      uint32_t ch;
							 | 
						||
| 
								 | 
							
								      Fecode++;
							 | 
						||
| 
								 | 
							
								      GETCHARINC(ch, Fecode);
							 | 
						||
| 
								 | 
							
								      GETCHARINC(fc, Feptr);
							 | 
						||
| 
								 | 
							
								      if (ch == fc)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        RRETURN(MATCH_NOMATCH);  /* Caseful match */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else if (Fop == OP_NOTI)   /* If caseless */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (ch > 127)
							 | 
						||
| 
								 | 
							
								          ch = UCD_OTHERCASE(ch);
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								          ch = (mb->fcc)[ch];
							 | 
						||
| 
								 | 
							
								        if (ch == fc) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* UCP without UTF is as above, but with one character per code unit. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else if (ucp)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      uint32_t ch;
							 | 
						||
| 
								 | 
							
								      fc = UCHAR21INC(Feptr);
							 | 
						||
| 
								 | 
							
								      ch = Fecode[1];
							 | 
						||
| 
								 | 
							
								      Fecode += 2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (ch == fc)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        RRETURN(MATCH_NOMATCH);  /* Caseful match */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else if (Fop == OP_NOTI)   /* If caseless */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (ch > 127)
							 | 
						||
| 
								 | 
							
								          ch = UCD_OTHERCASE(ch);
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								          ch = (mb->fcc)[ch];
							 | 
						||
| 
								 | 
							
								        if (ch == fc) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Neither UTF nor UCP is set */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      uint32_t ch = Fecode[1];
							 | 
						||
| 
								 | 
							
								      fc = UCHAR21INC(Feptr);
							 | 
						||
| 
								 | 
							
								      if (ch == fc || (Fop == OP_NOTI && TABLE_GET(ch, mb->fcc, ch) == fc))
							 | 
						||
| 
								 | 
							
								        RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      Fecode += 2;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match a single character repeatedly. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Loclength    F->temp_size
							 | 
						||
| 
								 | 
							
								#define Lstart_eptr  F->temp_sptr[0]
							 | 
						||
| 
								 | 
							
								#define Lcharptr     F->temp_sptr[1]
							 | 
						||
| 
								 | 
							
								#define Lmin         F->temp_32[0]
							 | 
						||
| 
								 | 
							
								#define Lmax         F->temp_32[1]
							 | 
						||
| 
								 | 
							
								#define Lc           F->temp_32[2]
							 | 
						||
| 
								 | 
							
								#define Loc          F->temp_32[3]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_EXACT:
							 | 
						||
| 
								 | 
							
								    case OP_EXACTI:
							 | 
						||
| 
								 | 
							
								    Lmin = Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_POSUPTO:
							 | 
						||
| 
								 | 
							
								    case OP_POSUPTOI:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_UPTO:
							 | 
						||
| 
								 | 
							
								    case OP_UPTOI:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_MAX;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_MINUPTO:
							 | 
						||
| 
								 | 
							
								    case OP_MINUPTOI:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_MIN;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_POSSTAR:
							 | 
						||
| 
								 | 
							
								    case OP_POSSTARI:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = UINT32_MAX;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    goto REPEATCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_POSPLUS:
							 | 
						||
| 
								 | 
							
								    case OP_POSPLUSI:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 1;
							 | 
						||
| 
								 | 
							
								    Lmax = UINT32_MAX;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    goto REPEATCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_POSQUERY:
							 | 
						||
| 
								 | 
							
								    case OP_POSQUERYI:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = 1;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    goto REPEATCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_STAR:
							 | 
						||
| 
								 | 
							
								    case OP_STARI:
							 | 
						||
| 
								 | 
							
								    case OP_MINSTAR:
							 | 
						||
| 
								 | 
							
								    case OP_MINSTARI:
							 | 
						||
| 
								 | 
							
								    case OP_PLUS:
							 | 
						||
| 
								 | 
							
								    case OP_PLUSI:
							 | 
						||
| 
								 | 
							
								    case OP_MINPLUS:
							 | 
						||
| 
								 | 
							
								    case OP_MINPLUSI:
							 | 
						||
| 
								 | 
							
								    case OP_QUERY:
							 | 
						||
| 
								 | 
							
								    case OP_QUERYI:
							 | 
						||
| 
								 | 
							
								    case OP_MINQUERY:
							 | 
						||
| 
								 | 
							
								    case OP_MINQUERYI:
							 | 
						||
| 
								 | 
							
								    fc = *Fecode++ - ((Fop < OP_STARI)? OP_STAR : OP_STARI);
							 | 
						||
| 
								 | 
							
								    Lmin = rep_min[fc];
							 | 
						||
| 
								 | 
							
								    Lmax = rep_max[fc];
							 | 
						||
| 
								 | 
							
								    reptype = rep_typ[fc];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Common code for all repeated single-character matches. We first check
							 | 
						||
| 
								 | 
							
								    for the minimum number of characters. If the minimum equals the maximum, we
							 | 
						||
| 
								 | 
							
								    are done. Otherwise, if minimizing, check the rest of the pattern for a
							 | 
						||
| 
								 | 
							
								    match; if there isn't one, advance up to the maximum, one character at a
							 | 
						||
| 
								 | 
							
								    time.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    If maximizing, advance up to the maximum number of matching characters,
							 | 
						||
| 
								 | 
							
								    until Feptr is past the end of the maximum run. If possessive, we are
							 | 
						||
| 
								 | 
							
								    then done (no backing up). Otherwise, match at this position; anything
							 | 
						||
| 
								 | 
							
								    other than no match is immediately returned. For nomatch, back up one
							 | 
						||
| 
								 | 
							
								    character, unless we are matching \R and the last thing matched was
							 | 
						||
| 
								 | 
							
								    \r\n, in which case, back up two code units until we reach the first
							 | 
						||
| 
								 | 
							
								    optional character position.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The various UTF/non-UTF and caseful/caseless cases are handled separately,
							 | 
						||
| 
								 | 
							
								    for speed. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    REPEATCHAR:
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								    if (utf)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Flength = 1;
							 | 
						||
| 
								 | 
							
								      Lcharptr = Fecode;
							 | 
						||
| 
								 | 
							
								      GETCHARLEN(fc, Fecode, Flength);
							 | 
						||
| 
								 | 
							
								      Fecode += Flength;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Handle multi-code-unit character matching, caseful and caseless. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (Flength > 1)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        uint32_t othercase;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (Fop >= OP_STARI &&     /* Caseless */
							 | 
						||
| 
								 | 
							
								            (othercase = UCD_OTHERCASE(fc)) != fc)
							 | 
						||
| 
								 | 
							
								          Loclength = PRIV(ord2utf)(othercase, Foccu);
							 | 
						||
| 
								 | 
							
								        else Loclength = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr <= mb->end_subject - Flength &&
							 | 
						||
| 
								 | 
							
								            memcmp(Feptr, Lcharptr, CU2BYTES(Flength)) == 0) Feptr += Flength;
							 | 
						||
| 
								 | 
							
								          else if (Loclength > 0 &&
							 | 
						||
| 
								 | 
							
								                   Feptr <= mb->end_subject - Loclength &&
							 | 
						||
| 
								 | 
							
								                   memcmp(Feptr, Foccu, CU2BYTES(Loclength)) == 0)
							 | 
						||
| 
								 | 
							
								            Feptr += Loclength;
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            CHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (Lmin == Lmax) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (reptype == REPTYPE_MIN)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM202);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr <= mb->end_subject - Flength &&
							 | 
						||
| 
								 | 
							
								              memcmp(Feptr, Lcharptr, CU2BYTES(Flength)) == 0) Feptr += Flength;
							 | 
						||
| 
								 | 
							
								            else if (Loclength > 0 &&
							 | 
						||
| 
								 | 
							
								                     Feptr <= mb->end_subject - Loclength &&
							 | 
						||
| 
								 | 
							
								                     memcmp(Feptr, Foccu, CU2BYTES(Loclength)) == 0)
							 | 
						||
| 
								 | 
							
								              Feptr += Loclength;
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              CHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        else  /* Maximize */
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          Lstart_eptr = Feptr;
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr <= mb->end_subject - Flength &&
							 | 
						||
| 
								 | 
							
								                memcmp(Feptr, Lcharptr, CU2BYTES(Flength)) == 0)
							 | 
						||
| 
								 | 
							
								              Feptr += Flength;
							 | 
						||
| 
								 | 
							
								            else if (Loclength > 0 &&
							 | 
						||
| 
								 | 
							
								                     Feptr <= mb->end_subject - Loclength &&
							 | 
						||
| 
								 | 
							
								                     memcmp(Feptr, Foccu, CU2BYTES(Loclength)) == 0)
							 | 
						||
| 
								 | 
							
								              Feptr += Loclength;
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              CHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* After \C in UTF mode, Lstart_eptr might be in the middle of a
							 | 
						||
| 
								 | 
							
								          Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't
							 | 
						||
| 
								 | 
							
								          go too far. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (reptype != REPTYPE_POS) for(;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr <= Lstart_eptr) break;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM203);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            Feptr--;
							 | 
						||
| 
								 | 
							
								            BACKCHAR(Feptr);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;   /* End of repeated wide character handling */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Length of UTF character is 1. Put it into the preserved variable and
							 | 
						||
| 
								 | 
							
								      fall through to the non-UTF code. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Lc = fc;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* When not in UTF mode, load a single-code-unit character. Then proceed as
							 | 
						||
| 
								 | 
							
								    above, using Unicode casing if either UTF or UCP is set. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Lc = *Fecode++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Caseless comparison */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Fop >= OP_STARI)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH == 8
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (ucp && !utf && Lc > 127) Loc = UCD_OTHERCASE(Lc);
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								      /* Lc will be < 128 in UTF-8 mode. */
							 | 
						||
| 
								 | 
							
								      Loc = mb->fcc[Lc];
							 | 
						||
| 
								 | 
							
								#else /* 16-bit & 32-bit */
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if ((utf || ucp) && Lc > 127) Loc = UCD_OTHERCASE(Lc);
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								      Loc = TABLE_GET(Lc, mb->fcc, Lc);
							 | 
						||
| 
								 | 
							
								#endif  /* PCRE2_CODE_UNIT_WIDTH == 8 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        uint32_t cc;                 /* Faster than PCRE2_UCHAR */
							 | 
						||
| 
								 | 
							
								        if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        cc = UCHAR21TEST(Feptr);
							 | 
						||
| 
								 | 
							
								        if (Lc != cc && Loc != cc) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        Feptr++;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      if (Lmin == Lmax) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (reptype == REPTYPE_MIN)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t cc;               /* Faster than PCRE2_UCHAR */
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM25);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          cc = UCHAR21TEST(Feptr);
							 | 
						||
| 
								 | 
							
								          if (Lc != cc && Loc != cc) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        /* Control never gets here */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else  /* Maximize */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        Lstart_eptr = Feptr;
							 | 
						||
| 
								 | 
							
								        for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t cc;               /* Faster than PCRE2_UCHAR */
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          cc = UCHAR21TEST(Feptr);
							 | 
						||
| 
								 | 
							
								          if (Lc != cc && Loc != cc) break;
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        if (reptype != REPTYPE_POS) for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr == Lstart_eptr) break;
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM26);
							 | 
						||
| 
								 | 
							
								          Feptr--;
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Caseful comparisons (includes all multi-byte characters) */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        if (Lc != UCHAR21INCTEST(Feptr)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (Lmin == Lmax) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (reptype == REPTYPE_MIN)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM27);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (Lc != UCHAR21INCTEST(Feptr)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        /* Control never gets here */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else  /* Maximize */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        Lstart_eptr = Feptr;
							 | 
						||
| 
								 | 
							
								        for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (Lc != UCHAR21TEST(Feptr)) break;
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (reptype != REPTYPE_POS) for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr <= Lstart_eptr) break;
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM28);
							 | 
						||
| 
								 | 
							
								          Feptr--;
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Loclength
							 | 
						||
| 
								 | 
							
								#undef Lstart_eptr
							 | 
						||
| 
								 | 
							
								#undef Lcharptr
							 | 
						||
| 
								 | 
							
								#undef Lmin
							 | 
						||
| 
								 | 
							
								#undef Lmax
							 | 
						||
| 
								 | 
							
								#undef Lc
							 | 
						||
| 
								 | 
							
								#undef Loc
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match a negated single one-byte character repeatedly. This is almost a
							 | 
						||
| 
								 | 
							
								    repeat of the code for a repeated single character, but I haven't found a
							 | 
						||
| 
								 | 
							
								    nice way of commoning these up that doesn't require a test of the
							 | 
						||
| 
								 | 
							
								    positive/negative option for each character match. Maybe that wouldn't add
							 | 
						||
| 
								 | 
							
								    very much to the time taken, but character matching *is* what this is all
							 | 
						||
| 
								 | 
							
								    about... */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lstart_eptr  F->temp_sptr[0]
							 | 
						||
| 
								 | 
							
								#define Lmin         F->temp_32[0]
							 | 
						||
| 
								 | 
							
								#define Lmax         F->temp_32[1]
							 | 
						||
| 
								 | 
							
								#define Lc           F->temp_32[2]
							 | 
						||
| 
								 | 
							
								#define Loc          F->temp_32[3]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOTEXACT:
							 | 
						||
| 
								 | 
							
								    case OP_NOTEXACTI:
							 | 
						||
| 
								 | 
							
								    Lmin = Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATNOTCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOTUPTO:
							 | 
						||
| 
								 | 
							
								    case OP_NOTUPTOI:
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_MAX;
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATNOTCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOTMINUPTO:
							 | 
						||
| 
								 | 
							
								    case OP_NOTMINUPTOI:
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_MIN;
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATNOTCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOTPOSSTAR:
							 | 
						||
| 
								 | 
							
								    case OP_NOTPOSSTARI:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = UINT32_MAX;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    goto REPEATNOTCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOTPOSPLUS:
							 | 
						||
| 
								 | 
							
								    case OP_NOTPOSPLUSI:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 1;
							 | 
						||
| 
								 | 
							
								    Lmax = UINT32_MAX;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    goto REPEATNOTCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOTPOSQUERY:
							 | 
						||
| 
								 | 
							
								    case OP_NOTPOSQUERYI:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = 1;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    goto REPEATNOTCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOTPOSUPTO:
							 | 
						||
| 
								 | 
							
								    case OP_NOTPOSUPTOI:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATNOTCHAR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOTSTAR:
							 | 
						||
| 
								 | 
							
								    case OP_NOTSTARI:
							 | 
						||
| 
								 | 
							
								    case OP_NOTMINSTAR:
							 | 
						||
| 
								 | 
							
								    case OP_NOTMINSTARI:
							 | 
						||
| 
								 | 
							
								    case OP_NOTPLUS:
							 | 
						||
| 
								 | 
							
								    case OP_NOTPLUSI:
							 | 
						||
| 
								 | 
							
								    case OP_NOTMINPLUS:
							 | 
						||
| 
								 | 
							
								    case OP_NOTMINPLUSI:
							 | 
						||
| 
								 | 
							
								    case OP_NOTQUERY:
							 | 
						||
| 
								 | 
							
								    case OP_NOTQUERYI:
							 | 
						||
| 
								 | 
							
								    case OP_NOTMINQUERY:
							 | 
						||
| 
								 | 
							
								    case OP_NOTMINQUERYI:
							 | 
						||
| 
								 | 
							
								    fc = *Fecode++ - ((Fop >= OP_NOTSTARI)? OP_NOTSTARI: OP_NOTSTAR);
							 | 
						||
| 
								 | 
							
								    Lmin = rep_min[fc];
							 | 
						||
| 
								 | 
							
								    Lmax = rep_max[fc];
							 | 
						||
| 
								 | 
							
								    reptype = rep_typ[fc];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Common code for all repeated single-character non-matches. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    REPEATNOTCHAR:
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(Lc, Fecode);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* The code is duplicated for the caseless and caseful cases, for speed,
							 | 
						||
| 
								 | 
							
								    since matching characters is likely to be quite common. First, ensure the
							 | 
						||
| 
								 | 
							
								    minimum number of matches are present. If Lmin = Lmax, we are done.
							 | 
						||
| 
								 | 
							
								    Otherwise, if minimizing, keep trying the rest of the expression and
							 | 
						||
| 
								 | 
							
								    advancing one matching character if failing, up to the maximum.
							 | 
						||
| 
								 | 
							
								    Alternatively, if maximizing, find the maximum number of characters and
							 | 
						||
| 
								 | 
							
								    work backwards. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Fop >= OP_NOTSTARI)     /* Caseless */
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if ((utf || ucp) && Lc > 127)
							 | 
						||
| 
								 | 
							
								        Loc = UCD_OTHERCASE(Lc);
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Loc = TABLE_GET(Lc, mb->fcc, Lc);  /* Other case from table */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (utf)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        uint32_t d;
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GETCHARINC(d, Feptr);
							 | 
						||
| 
								 | 
							
								          if (Lc == d || Loc == d) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (Lc == *Feptr || Loc == *Feptr) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (Lmin == Lmax) continue;  /* Finished for exact count */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (reptype == REPTYPE_MIN)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								        if (utf)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t d;
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM204);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINC(d, Feptr);
							 | 
						||
| 
								 | 
							
								            if (Lc == d || Loc == d) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								#endif  /*SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM29);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (Lc == *Feptr || Loc == *Feptr) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        /* Control never gets here */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Maximize case */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        Lstart_eptr = Feptr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								        if (utf)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t d;
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(d, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (Lc == d || Loc == d) break;
							 | 
						||
| 
								 | 
							
								            Feptr += len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* After \C in UTF mode, Lstart_eptr might be in the middle of a
							 | 
						||
| 
								 | 
							
								          Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't
							 | 
						||
| 
								 | 
							
								          go too far. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (reptype != REPTYPE_POS) for(;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr <= Lstart_eptr) break;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM205);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            Feptr--;
							 | 
						||
| 
								 | 
							
								            BACKCHAR(Feptr);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (Lc == *Feptr || Loc == *Feptr) break;
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (reptype != REPTYPE_POS) for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr == Lstart_eptr) break;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM30);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            Feptr--;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Caseful comparisons */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (utf)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        uint32_t d;
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GETCHARINC(d, Feptr);
							 | 
						||
| 
								 | 
							
								          if (Lc == d) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								      /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (Lc == *Feptr++) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (Lmin == Lmax) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (reptype == REPTYPE_MIN)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								        if (utf)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t d;
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM206);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINC(d, Feptr);
							 | 
						||
| 
								 | 
							
								            if (Lc == d) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM31);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (Lc == *Feptr++) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        /* Control never gets here */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Maximize case */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        Lstart_eptr = Feptr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								        if (utf)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t d;
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(d, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (Lc == d) break;
							 | 
						||
| 
								 | 
							
								            Feptr += len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* After \C in UTF mode, Lstart_eptr might be in the middle of a
							 | 
						||
| 
								 | 
							
								          Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't
							 | 
						||
| 
								 | 
							
								          go too far. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (reptype != REPTYPE_POS) for(;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr <= Lstart_eptr) break;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM207);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            Feptr--;
							 | 
						||
| 
								 | 
							
								            BACKCHAR(Feptr);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (Lc == *Feptr) break;
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (reptype != REPTYPE_POS) for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr == Lstart_eptr) break;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM32);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            Feptr--;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lstart_eptr
							 | 
						||
| 
								 | 
							
								#undef Lmin
							 | 
						||
| 
								 | 
							
								#undef Lmax
							 | 
						||
| 
								 | 
							
								#undef Lc
							 | 
						||
| 
								 | 
							
								#undef Loc
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match a bit-mapped character class, possibly repeatedly. These opcodes
							 | 
						||
| 
								 | 
							
								    are 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 0-127 when UTF processing is enabled. The only difference between
							 | 
						||
| 
								 | 
							
								    OP_CLASS and OP_NCLASS occurs when a data character outside the range is
							 | 
						||
| 
								 | 
							
								    encountered. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lmin               F->temp_32[0]
							 | 
						||
| 
								 | 
							
								#define Lmax               F->temp_32[1]
							 | 
						||
| 
								 | 
							
								#define Lstart_eptr        F->temp_sptr[0]
							 | 
						||
| 
								 | 
							
								#define Lbyte_map_address  F->temp_sptr[1]
							 | 
						||
| 
								 | 
							
								#define Lbyte_map          ((unsigned char *)Lbyte_map_address)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NCLASS:
							 | 
						||
| 
								 | 
							
								    case OP_CLASS:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Lbyte_map_address = Fecode + 1;           /* Save for matching */
							 | 
						||
| 
								 | 
							
								      Fecode += 1 + (32 / sizeof(PCRE2_UCHAR)); /* Advance past the item */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Look past the end of the item to see if there is repeat information
							 | 
						||
| 
								 | 
							
								      following. Then obey similar code to character type repeats. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      switch (*Fecode)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        case OP_CRSTAR:
							 | 
						||
| 
								 | 
							
								        case OP_CRMINSTAR:
							 | 
						||
| 
								 | 
							
								        case OP_CRPLUS:
							 | 
						||
| 
								 | 
							
								        case OP_CRMINPLUS:
							 | 
						||
| 
								 | 
							
								        case OP_CRQUERY:
							 | 
						||
| 
								 | 
							
								        case OP_CRMINQUERY:
							 | 
						||
| 
								 | 
							
								        case OP_CRPOSSTAR:
							 | 
						||
| 
								 | 
							
								        case OP_CRPOSPLUS:
							 | 
						||
| 
								 | 
							
								        case OP_CRPOSQUERY:
							 | 
						||
| 
								 | 
							
								        fc = *Fecode++ - OP_CRSTAR;
							 | 
						||
| 
								 | 
							
								        Lmin = rep_min[fc];
							 | 
						||
| 
								 | 
							
								        Lmax = rep_max[fc];
							 | 
						||
| 
								 | 
							
								        reptype = rep_typ[fc];
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_CRRANGE:
							 | 
						||
| 
								 | 
							
								        case OP_CRMINRANGE:
							 | 
						||
| 
								 | 
							
								        case OP_CRPOSRANGE:
							 | 
						||
| 
								 | 
							
								        Lmin = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								        Lmax = GET2(Fecode, 1 + IMM2_SIZE);
							 | 
						||
| 
								 | 
							
								        if (Lmax == 0) Lmax = UINT32_MAX;       /* Max 0 => infinity */
							 | 
						||
| 
								 | 
							
								        reptype = rep_typ[*Fecode - OP_CRSTAR];
							 | 
						||
| 
								 | 
							
								        Fecode += 1 + 2 * IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        default:               /* No repeat follows */
							 | 
						||
| 
								 | 
							
								        Lmin = Lmax = 1;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* First, ensure the minimum number of matches are present. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (utf)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GETCHARINC(fc, Feptr);
							 | 
						||
| 
								 | 
							
								          if (fc > 255)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Fop == OP_CLASS) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								            if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								      /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          fc = *Feptr++;
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								          if (fc > 255)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Fop == OP_CLASS) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								          if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If Lmax == Lmin we are done. Continue with main loop. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (Lmin == Lmax) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If minimizing, keep testing the rest of the expression and advancing
							 | 
						||
| 
								 | 
							
								      the pointer while it matches the class. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (reptype == REPTYPE_MIN)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								        if (utf)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM200);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINC(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if (fc > 255)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (Fop == OP_CLASS) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								              if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM23);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            fc = *Feptr++;
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								            if (fc > 255)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (Fop == OP_CLASS) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        /* Control never gets here */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If maximizing, find the longest possible run, then work backwards. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        Lstart_eptr = Feptr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								        if (utf)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (fc > 255)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (Fop == OP_CLASS) break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								              if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) break;
							 | 
						||
| 
								 | 
							
								            Feptr += len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (reptype == REPTYPE_POS) continue;    /* No backtracking */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* After \C in UTF mode, Lstart_eptr might be in the middle of a
							 | 
						||
| 
								 | 
							
								          Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't
							 | 
						||
| 
								 | 
							
								          go too far. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM201);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Feptr-- <= Lstart_eptr) break;  /* Tried at original position */
							 | 
						||
| 
								 | 
							
								            BACKCHAR(Feptr);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								          /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            fc = *Feptr;
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								            if (fc > 255)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (Fop == OP_CLASS) break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) break;
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (reptype == REPTYPE_POS) continue;    /* No backtracking */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          while (Feptr >= Lstart_eptr)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM24);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            Feptr--;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lbyte_map_address
							 | 
						||
| 
								 | 
							
								#undef Lbyte_map
							 | 
						||
| 
								 | 
							
								#undef Lstart_eptr
							 | 
						||
| 
								 | 
							
								#undef Lmin
							 | 
						||
| 
								 | 
							
								#undef Lmax
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match an extended character class. In the 8-bit library, this opcode is
							 | 
						||
| 
								 | 
							
								    encountered only when UTF-8 mode mode is supported. In the 16-bit and
							 | 
						||
| 
								 | 
							
								    32-bit libraries, codepoints greater than 255 may be encountered even when
							 | 
						||
| 
								 | 
							
								    UTF is not supported. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lstart_eptr  F->temp_sptr[0]
							 | 
						||
| 
								 | 
							
								#define Lxclass_data F->temp_sptr[1]
							 | 
						||
| 
								 | 
							
								#define Lmin         F->temp_32[0]
							 | 
						||
| 
								 | 
							
								#define Lmax         F->temp_32[1]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_WIDE_CHARS
							 | 
						||
| 
								 | 
							
								    case OP_XCLASS:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Lxclass_data = Fecode + 1 + LINK_SIZE;  /* Save for matching */
							 | 
						||
| 
								 | 
							
								      Fecode += GET(Fecode, 1);               /* Advance past the item */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      switch (*Fecode)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        case OP_CRSTAR:
							 | 
						||
| 
								 | 
							
								        case OP_CRMINSTAR:
							 | 
						||
| 
								 | 
							
								        case OP_CRPLUS:
							 | 
						||
| 
								 | 
							
								        case OP_CRMINPLUS:
							 | 
						||
| 
								 | 
							
								        case OP_CRQUERY:
							 | 
						||
| 
								 | 
							
								        case OP_CRMINQUERY:
							 | 
						||
| 
								 | 
							
								        case OP_CRPOSSTAR:
							 | 
						||
| 
								 | 
							
								        case OP_CRPOSPLUS:
							 | 
						||
| 
								 | 
							
								        case OP_CRPOSQUERY:
							 | 
						||
| 
								 | 
							
								        fc = *Fecode++ - OP_CRSTAR;
							 | 
						||
| 
								 | 
							
								        Lmin = rep_min[fc];
							 | 
						||
| 
								 | 
							
								        Lmax = rep_max[fc];
							 | 
						||
| 
								 | 
							
								        reptype = rep_typ[fc];
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_CRRANGE:
							 | 
						||
| 
								 | 
							
								        case OP_CRMINRANGE:
							 | 
						||
| 
								 | 
							
								        case OP_CRPOSRANGE:
							 | 
						||
| 
								 | 
							
								        Lmin = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								        Lmax = GET2(Fecode, 1 + IMM2_SIZE);
							 | 
						||
| 
								 | 
							
								        if (Lmax == 0) Lmax = UINT32_MAX;  /* Max 0 => infinity */
							 | 
						||
| 
								 | 
							
								        reptype = rep_typ[*Fecode - OP_CRSTAR];
							 | 
						||
| 
								 | 
							
								        Fecode += 1 + 2 * IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        default:               /* No repeat follows */
							 | 
						||
| 
								 | 
							
								        Lmin = Lmax = 1;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* First, ensure the minimum number of matches are present. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								        if (!PRIV(xclass)(fc, Lxclass_data, utf)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If Lmax == Lmin we can just continue with the main loop. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (Lmin == Lmax) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If minimizing, keep testing the rest of the expression and advancing
							 | 
						||
| 
								 | 
							
								      the pointer while it matches the class. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (reptype == REPTYPE_MIN)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM100);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								          if (!PRIV(xclass)(fc, Lxclass_data, utf)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        /* Control never gets here */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If maximizing, find the longest possible run, then work backwards. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        Lstart_eptr = Feptr;
							 | 
						||
| 
								 | 
							
								        for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          int len = 1;
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								          GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								          fc = *Feptr;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								          if (!PRIV(xclass)(fc, Lxclass_data, utf)) break;
							 | 
						||
| 
								 | 
							
								          Feptr += len;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (reptype == REPTYPE_POS) continue;    /* No backtracking */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* After \C in UTF mode, Lstart_eptr might be in the middle of a
							 | 
						||
| 
								 | 
							
								        Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't
							 | 
						||
| 
								 | 
							
								        go too far. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for(;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM101);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          if (Feptr-- <= Lstart_eptr) break;  /* Tried at original position */
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								          if (utf) BACKCHAR(Feptr);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Control never gets here */
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_WIDE_CHARS: end of XCLASS */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lstart_eptr
							 | 
						||
| 
								 | 
							
								#undef Lxclass_data
							 | 
						||
| 
								 | 
							
								#undef Lmin
							 | 
						||
| 
								 | 
							
								#undef Lmax
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match various character types when PCRE2_UCP is not set. These opcodes
							 | 
						||
| 
								 | 
							
								    are not generated when PCRE2_UCP is set - instead appropriate property
							 | 
						||
| 
								 | 
							
								    tests are compiled. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOT_DIGIT:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    if (CHMAX_255(fc) && (mb->ctypes[fc] & ctype_digit) != 0)
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_DIGIT:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    if (!CHMAX_255(fc) || (mb->ctypes[fc] & ctype_digit) == 0)
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOT_WHITESPACE:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    if (CHMAX_255(fc) && (mb->ctypes[fc] & ctype_space) != 0)
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_WHITESPACE:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    if (!CHMAX_255(fc) || (mb->ctypes[fc] & ctype_space) == 0)
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOT_WORDCHAR:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    if (CHMAX_255(fc) && (mb->ctypes[fc] & ctype_word) != 0)
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_WORDCHAR:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    if (!CHMAX_255(fc) || (mb->ctypes[fc] & ctype_word) == 0)
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_ANYNL:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    switch(fc)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case CHAR_CR:
							 | 
						||
| 
								 | 
							
								      if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else if (UCHAR21TEST(Feptr) == CHAR_LF) Feptr++;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case CHAR_LF:
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case CHAR_VT:
							 | 
						||
| 
								 | 
							
								      case CHAR_FF:
							 | 
						||
| 
								 | 
							
								      case CHAR_NEL:
							 | 
						||
| 
								 | 
							
								#ifndef EBCDIC
							 | 
						||
| 
								 | 
							
								      case 0x2028:
							 | 
						||
| 
								 | 
							
								      case 0x2029:
							 | 
						||
| 
								 | 
							
								#endif  /* Not EBCDIC */
							 | 
						||
| 
								 | 
							
								      if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOT_HSPACE:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    switch(fc)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      HSPACE_CASES: RRETURN(MATCH_NOMATCH);  /* Byte and multibyte cases */
							 | 
						||
| 
								 | 
							
								      default: break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_HSPACE:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    switch(fc)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      HSPACE_CASES: break;  /* Byte and multibyte cases */
							 | 
						||
| 
								 | 
							
								      default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOT_VSPACE:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    switch(fc)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      VSPACE_CASES: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      default: break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_VSPACE:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								    switch(fc)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      VSPACE_CASES: break;
							 | 
						||
| 
								 | 
							
								      default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Check the next character by Unicode property. We will get here only
							 | 
						||
| 
								 | 
							
								    if the support is in the binary; otherwise a compile-time error occurs. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_PROP:
							 | 
						||
| 
								 | 
							
								    case OP_NOTPROP:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      const uint32_t *cp;
							 | 
						||
| 
								 | 
							
								      const ucd_record *prop = GET_UCD(fc);
							 | 
						||
| 
								 | 
							
								      BOOL notmatch = Fop == OP_NOTPROP;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      switch(Fecode[1])
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        case PT_ANY:
							 | 
						||
| 
								 | 
							
								        if (notmatch) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_LAMP:
							 | 
						||
| 
								 | 
							
								        if ((prop->chartype == ucp_Lu ||
							 | 
						||
| 
								 | 
							
								             prop->chartype == ucp_Ll ||
							 | 
						||
| 
								 | 
							
								             prop->chartype == ucp_Lt) == notmatch)
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_GC:
							 | 
						||
| 
								 | 
							
								        if ((Fecode[2] == PRIV(ucp_gentype)[prop->chartype]) == notmatch)
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_PC:
							 | 
						||
| 
								 | 
							
								        if ((Fecode[2] == prop->chartype) == notmatch)
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_SC:
							 | 
						||
| 
								 | 
							
								        if ((Fecode[2] == prop->script) == notmatch)
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_SCX:
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          BOOL ok = (Fecode[2] == prop->script ||
							 | 
						||
| 
								 | 
							
								                     MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), Fecode[2]) != 0);
							 | 
						||
| 
								 | 
							
								          if (ok == notmatch) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* These are specials */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_ALNUM:
							 | 
						||
| 
								 | 
							
								        if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
							 | 
						||
| 
								 | 
							
								             PRIV(ucp_gentype)[prop->chartype] == ucp_N) == notmatch)
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* Perl space used to exclude VT, but from Perl 5.18 it is included,
							 | 
						||
| 
								 | 
							
								        which means that Perl space and POSIX space are now identical. PCRE
							 | 
						||
| 
								 | 
							
								        was changed at release 8.34. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_SPACE:    /* Perl space */
							 | 
						||
| 
								 | 
							
								        case PT_PXSPACE:  /* POSIX space */
							 | 
						||
| 
								 | 
							
								        switch(fc)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          HSPACE_CASES:
							 | 
						||
| 
								 | 
							
								          VSPACE_CASES:
							 | 
						||
| 
								 | 
							
								          if (notmatch) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          default:
							 | 
						||
| 
								 | 
							
								          if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == notmatch)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_WORD:
							 | 
						||
| 
								 | 
							
								        if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
							 | 
						||
| 
								 | 
							
								             PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
							 | 
						||
| 
								 | 
							
								             fc == CHAR_UNDERSCORE) == notmatch)
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_CLIST:
							 | 
						||
| 
								 | 
							
								        cp = PRIV(ucd_caseless_sets) + Fecode[2];
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (fc < *cp)
							 | 
						||
| 
								 | 
							
								            { if (notmatch) break; else { RRETURN(MATCH_NOMATCH); } }
							 | 
						||
| 
								 | 
							
								          if (fc == *cp++)
							 | 
						||
| 
								 | 
							
								            { if (notmatch) { RRETURN(MATCH_NOMATCH); } else break; }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_UCNC:
							 | 
						||
| 
								 | 
							
								        if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT ||
							 | 
						||
| 
								 | 
							
								             fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) ||
							 | 
						||
| 
								 | 
							
								             fc >= 0xe000) == notmatch)
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_BIDICL:
							 | 
						||
| 
								 | 
							
								        if ((UCD_BIDICLASS_PROP(prop) == Fecode[2]) == notmatch)
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case PT_BOOL:
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          BOOL ok = MAPBIT(PRIV(ucd_boolprop_sets) +
							 | 
						||
| 
								 | 
							
								            UCD_BPROPS_PROP(prop), Fecode[2]) != 0;
							 | 
						||
| 
								 | 
							
								          if (ok == notmatch) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* This should never occur */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        default:
							 | 
						||
| 
								 | 
							
								        return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Fecode += 3;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match an extended Unicode sequence. We will get here only if the support
							 | 
						||
| 
								 | 
							
								    is in the binary; otherwise a compile-time error occurs. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_EXTUNI:
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								      Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject, utf,
							 | 
						||
| 
								 | 
							
								        NULL);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    CHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match a single character type repeatedly. Note that the property type
							 | 
						||
| 
								 | 
							
								    does not need to be in a stack frame as it is not used within an RMATCH()
							 | 
						||
| 
								 | 
							
								    loop. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lstart_eptr  F->temp_sptr[0]
							 | 
						||
| 
								 | 
							
								#define Lmin         F->temp_32[0]
							 | 
						||
| 
								 | 
							
								#define Lmax         F->temp_32[1]
							 | 
						||
| 
								 | 
							
								#define Lctype       F->temp_32[2]
							 | 
						||
| 
								 | 
							
								#define Lpropvalue   F->temp_32[3]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_TYPEEXACT:
							 | 
						||
| 
								 | 
							
								    Lmin = Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATTYPE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_TYPEUPTO:
							 | 
						||
| 
								 | 
							
								    case OP_TYPEMINUPTO:
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    reptype = (*Fecode == OP_TYPEMINUPTO)? REPTYPE_MIN : REPTYPE_MAX;
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATTYPE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_TYPEPOSSTAR:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = UINT32_MAX;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    goto REPEATTYPE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_TYPEPOSPLUS:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 1;
							 | 
						||
| 
								 | 
							
								    Lmax = UINT32_MAX;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    goto REPEATTYPE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_TYPEPOSQUERY:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = 1;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    goto REPEATTYPE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_TYPEPOSUPTO:
							 | 
						||
| 
								 | 
							
								    reptype = REPTYPE_POS;
							 | 
						||
| 
								 | 
							
								    Lmin = 0;
							 | 
						||
| 
								 | 
							
								    Lmax = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								    goto REPEATTYPE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_TYPESTAR:
							 | 
						||
| 
								 | 
							
								    case OP_TYPEMINSTAR:
							 | 
						||
| 
								 | 
							
								    case OP_TYPEPLUS:
							 | 
						||
| 
								 | 
							
								    case OP_TYPEMINPLUS:
							 | 
						||
| 
								 | 
							
								    case OP_TYPEQUERY:
							 | 
						||
| 
								 | 
							
								    case OP_TYPEMINQUERY:
							 | 
						||
| 
								 | 
							
								    fc = *Fecode++ - OP_TYPESTAR;
							 | 
						||
| 
								 | 
							
								    Lmin = rep_min[fc];
							 | 
						||
| 
								 | 
							
								    Lmax = rep_max[fc];
							 | 
						||
| 
								 | 
							
								    reptype = rep_typ[fc];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Common code for all repeated character type matches. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    REPEATTYPE:
							 | 
						||
| 
								 | 
							
								    Lctype = *Fecode++;      /* Code for the character type */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								    if (Lctype == OP_PROP || Lctype == OP_NOTPROP)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      proptype = *Fecode++;
							 | 
						||
| 
								 | 
							
								      Lpropvalue = *Fecode++;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else proptype = -1;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* 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
							 | 
						||
| 
								 | 
							
								    (i.e. keep it out of the loops). As there are no calls to RMATCH in the
							 | 
						||
| 
								 | 
							
								    loops, we can use an ordinary variable for "notmatch". The code for UTF
							 | 
						||
| 
								 | 
							
								    mode is separated out for tidiness, except for Unicode property tests. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Lmin > 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (proptype >= 0)  /* Property tests in all modes */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        BOOL notmatch = Lctype == OP_NOTPROP;
							 | 
						||
| 
								 | 
							
								        switch(proptype)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          case PT_ANY:
							 | 
						||
| 
								 | 
							
								          if (notmatch) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_LAMP:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int chartype;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            chartype = UCD_CHARTYPE(fc);
							 | 
						||
| 
								 | 
							
								            if ((chartype == ucp_Lu ||
							 | 
						||
| 
								 | 
							
								                 chartype == ucp_Ll ||
							 | 
						||
| 
								 | 
							
								                 chartype == ucp_Lt) == notmatch)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_GC:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if ((UCD_CATEGORY(fc) == Lpropvalue) == notmatch)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_PC:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if ((UCD_CHARTYPE(fc) == Lpropvalue) == notmatch)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_SC:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if ((UCD_SCRIPT(fc) == Lpropvalue) == notmatch)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_SCX:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            BOOL ok;
							 | 
						||
| 
								 | 
							
								            const ucd_record *prop;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            prop = GET_UCD(fc);
							 | 
						||
| 
								 | 
							
								            ok = (prop->script == Lpropvalue ||
							 | 
						||
| 
								 | 
							
								                  MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), Lpropvalue) != 0);
							 | 
						||
| 
								 | 
							
								            if (ok == notmatch)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_ALNUM:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int category;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            category = UCD_CATEGORY(fc);
							 | 
						||
| 
								 | 
							
								            if ((category == ucp_L || category == ucp_N) == notmatch)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* Perl space used to exclude VT, but from Perl 5.18 it is included,
							 | 
						||
| 
								 | 
							
								          which means that Perl space and POSIX space are now identical. PCRE
							 | 
						||
| 
								 | 
							
								          was changed at release 8.34. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_SPACE:    /* Perl space */
							 | 
						||
| 
								 | 
							
								          case PT_PXSPACE:  /* POSIX space */
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              HSPACE_CASES:
							 | 
						||
| 
								 | 
							
								              VSPACE_CASES:
							 | 
						||
| 
								 | 
							
								              if (notmatch) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              default:
							 | 
						||
| 
								 | 
							
								              if ((UCD_CATEGORY(fc) == ucp_Z) == notmatch)
							 | 
						||
| 
								 | 
							
								                RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_WORD:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int category;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            category = UCD_CATEGORY(fc);
							 | 
						||
| 
								 | 
							
								            if ((category == ucp_L || category == ucp_N ||
							 | 
						||
| 
								 | 
							
								                fc == CHAR_UNDERSCORE) == notmatch)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_CLIST:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            const uint32_t *cp;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            cp = PRIV(ucd_caseless_sets) + Lpropvalue;
							 | 
						||
| 
								 | 
							
								            for (;;)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (fc < *cp)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                if (notmatch) break;
							 | 
						||
| 
								 | 
							
								                RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								              if (fc == *cp++)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                if (notmatch) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_UCNC:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT ||
							 | 
						||
| 
								 | 
							
								                 fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) ||
							 | 
						||
| 
								 | 
							
								                 fc >= 0xe000) == notmatch)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_BIDICL:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if ((UCD_BIDICLASS(fc) == Lpropvalue) == notmatch)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_BOOL:
							 | 
						||
| 
								 | 
							
								          for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            BOOL ok;
							 | 
						||
| 
								 | 
							
								            const ucd_record *prop;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            prop = GET_UCD(fc);
							 | 
						||
| 
								 | 
							
								            ok = MAPBIT(PRIV(ucd_boolprop_sets) +
							 | 
						||
| 
								 | 
							
								              UCD_BPROPS_PROP(prop), Lpropvalue) != 0;
							 | 
						||
| 
								 | 
							
								            if (ok == notmatch)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* This should not occur */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          default:
							 | 
						||
| 
								 | 
							
								          return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Match extended Unicode sequences. We will get here only if the
							 | 
						||
| 
								 | 
							
								      support is in the binary; otherwise a compile-time error occurs. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else if (Lctype == OP_EXTUNI)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject,
							 | 
						||
| 
								 | 
							
								              mb->end_subject, utf, NULL);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          CHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif     /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Handle all other cases in UTF mode */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (utf) switch(Lctype)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        case OP_ANY:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (IS_NEWLINE(Feptr)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          if (mb->partial != 0 &&
							 | 
						||
| 
								 | 
							
								              Feptr + 1 >= mb->end_subject &&
							 | 
						||
| 
								 | 
							
								              NLBLOCK->nltype == NLTYPE_FIXED &&
							 | 
						||
| 
								 | 
							
								              NLBLOCK->nllen == 2 &&
							 | 
						||
| 
								 | 
							
								              UCHAR21(Feptr) == NLBLOCK->nl[0])
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								            if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_ALLANY:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_ANYBYTE:
							 | 
						||
| 
								 | 
							
								        if (Feptr > mb->end_subject - Lmin) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        Feptr += Lmin;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_ANYNL:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GETCHARINC(fc, Feptr);
							 | 
						||
| 
								 | 
							
								          switch(fc)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case CHAR_CR:
							 | 
						||
| 
								 | 
							
								            if (Feptr < mb->end_subject && UCHAR21(Feptr) == CHAR_LF) Feptr++;
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case CHAR_LF:
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case CHAR_VT:
							 | 
						||
| 
								 | 
							
								            case CHAR_FF:
							 | 
						||
| 
								 | 
							
								            case CHAR_NEL:
							 | 
						||
| 
								 | 
							
								#ifndef EBCDIC
							 | 
						||
| 
								 | 
							
								            case 0x2028:
							 | 
						||
| 
								 | 
							
								            case 0x2029:
							 | 
						||
| 
								 | 
							
								#endif  /* Not EBCDIC */
							 | 
						||
| 
								 | 
							
								            if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_NOT_HSPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GETCHARINC(fc, Feptr);
							 | 
						||
| 
								 | 
							
								          switch(fc)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            HSPACE_CASES: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            default: break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_HSPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GETCHARINC(fc, Feptr);
							 | 
						||
| 
								 | 
							
								          switch(fc)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            HSPACE_CASES: break;
							 | 
						||
| 
								 | 
							
								            default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_NOT_VSPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GETCHARINC(fc, Feptr);
							 | 
						||
| 
								 | 
							
								          switch(fc)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            VSPACE_CASES: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            default: break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_VSPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GETCHARINC(fc, Feptr);
							 | 
						||
| 
								 | 
							
								          switch(fc)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            VSPACE_CASES: break;
							 | 
						||
| 
								 | 
							
								            default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_NOT_DIGIT:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GETCHARINC(fc, Feptr);
							 | 
						||
| 
								 | 
							
								          if (fc < 128 && (mb->ctypes[fc] & ctype_digit) != 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_DIGIT:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t cc;
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          cc = UCHAR21(Feptr);
							 | 
						||
| 
								 | 
							
								          if (cc >= 128 || (mb->ctypes[cc] & ctype_digit) == 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          /* No need to skip more code units - we know it has only one. */
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_NOT_WHITESPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t cc;
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          cc = UCHAR21(Feptr);
							 | 
						||
| 
								 | 
							
								          if (cc < 128 && (mb->ctypes[cc] & ctype_space) != 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_WHITESPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t cc;
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          cc = UCHAR21(Feptr);
							 | 
						||
| 
								 | 
							
								          if (cc >= 128 || (mb->ctypes[cc] & ctype_space) == 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          /* No need to skip more code units - we know it has only one. */
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_NOT_WORDCHAR:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t cc;
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          cc = UCHAR21(Feptr);
							 | 
						||
| 
								 | 
							
								          if (cc < 128 && (mb->ctypes[cc] & ctype_word) != 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_WORDCHAR:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t cc;
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          cc = UCHAR21(Feptr);
							 | 
						||
| 
								 | 
							
								          if (cc >= 128 || (mb->ctypes[cc] & ctype_word) == 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          /* No need to skip more code units - we know it has only one. */
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        default:
							 | 
						||
| 
								 | 
							
								        return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								        }  /* End switch(Lctype) */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif     /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Code for the non-UTF case for minimum matching of operators other
							 | 
						||
| 
								 | 
							
								      than OP_PROP and OP_NOTPROP. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      switch(Lctype)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        case OP_ANY:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (IS_NEWLINE(Feptr)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          if (mb->partial != 0 &&
							 | 
						||
| 
								 | 
							
								              Feptr + 1 >= mb->end_subject &&
							 | 
						||
| 
								 | 
							
								              NLBLOCK->nltype == NLTYPE_FIXED &&
							 | 
						||
| 
								 | 
							
								              NLBLOCK->nllen == 2 &&
							 | 
						||
| 
								 | 
							
								              *Feptr == NLBLOCK->nl[0])
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								            if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_ALLANY:
							 | 
						||
| 
								 | 
							
								        if (Feptr > mb->end_subject - Lmin)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        Feptr += Lmin;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* This OP_ANYBYTE case will never be reached because \C gets turned
							 | 
						||
| 
								 | 
							
								        into OP_ALLANY in non-UTF mode. Cut out the code so that coverage
							 | 
						||
| 
								 | 
							
								        reports don't complain about it's never being used. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*        case OP_ANYBYTE:
							 | 
						||
| 
								 | 
							
								*        if (Feptr > mb->end_subject - Lmin)
							 | 
						||
| 
								 | 
							
								*          {
							 | 
						||
| 
								 | 
							
								*          SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								*          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								*          }
							 | 
						||
| 
								 | 
							
								*        Feptr += Lmin;
							 | 
						||
| 
								 | 
							
								*        break;
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								        case OP_ANYNL:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          switch(*Feptr++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case CHAR_CR:
							 | 
						||
| 
								 | 
							
								            if (Feptr < mb->end_subject && *Feptr == CHAR_LF) Feptr++;
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case CHAR_LF:
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case CHAR_VT:
							 | 
						||
| 
								 | 
							
								            case CHAR_FF:
							 | 
						||
| 
								 | 
							
								            case CHAR_NEL:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								            case 0x2028:
							 | 
						||
| 
								 | 
							
								            case 0x2029:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_NOT_HSPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          switch(*Feptr++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            default: break;
							 | 
						||
| 
								 | 
							
								            HSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								            HSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_HSPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          switch(*Feptr++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            HSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								            HSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_NOT_VSPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          switch(*Feptr++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            VSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								            VSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            default: break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_VSPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          switch(*Feptr++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            VSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								            VSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_NOT_DIGIT:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_digit) != 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_DIGIT:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_digit) == 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_NOT_WHITESPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_space) != 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_WHITESPACE:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_space) == 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_NOT_WORDCHAR:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_word) != 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case OP_WORDCHAR:
							 | 
						||
| 
								 | 
							
								        for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_word) == 0)
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          Feptr++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        default:
							 | 
						||
| 
								 | 
							
								        return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If Lmin = Lmax we are done. Continue with the main loop. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Lmin == Lmax) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If minimizing, we have to test the rest of the pattern before each
							 | 
						||
| 
								 | 
							
								    subsequent match. This means we cannot use a local "notmatch" variable as
							 | 
						||
| 
								 | 
							
								    in the other cases. As all 4 temporary 32-bit values in the frame are
							 | 
						||
| 
								 | 
							
								    already in use, just test the type each time. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (reptype == REPTYPE_MIN)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (proptype >= 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        switch(proptype)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          case PT_ANY:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM208);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_LAMP:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int chartype;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM209);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            chartype = UCD_CHARTYPE(fc);
							 | 
						||
| 
								 | 
							
								            if ((chartype == ucp_Lu ||
							 | 
						||
| 
								 | 
							
								                 chartype == ucp_Ll ||
							 | 
						||
| 
								 | 
							
								                 chartype == ucp_Lt) == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_GC:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM210);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if ((UCD_CATEGORY(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_PC:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM211);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if ((UCD_CHARTYPE(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_SC:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM212);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if ((UCD_SCRIPT(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_SCX:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            BOOL ok;
							 | 
						||
| 
								 | 
							
								            const ucd_record *prop;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM225);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            prop = GET_UCD(fc);
							 | 
						||
| 
								 | 
							
								            ok = (prop->script == Lpropvalue
							 | 
						||
| 
								 | 
							
								                  || MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), Lpropvalue) != 0);
							 | 
						||
| 
								 | 
							
								            if (ok == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_ALNUM:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int category;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM213);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            category = UCD_CATEGORY(fc);
							 | 
						||
| 
								 | 
							
								            if ((category == ucp_L || category == ucp_N) == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* Perl space used to exclude VT, but from Perl 5.18 it is included,
							 | 
						||
| 
								 | 
							
								          which means that Perl space and POSIX space are now identical. PCRE
							 | 
						||
| 
								 | 
							
								          was changed at release 8.34. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_SPACE:    /* Perl space */
							 | 
						||
| 
								 | 
							
								          case PT_PXSPACE:  /* POSIX space */
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM214);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              HSPACE_CASES:
							 | 
						||
| 
								 | 
							
								              VSPACE_CASES:
							 | 
						||
| 
								 | 
							
								              if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              default:
							 | 
						||
| 
								 | 
							
								              if ((UCD_CATEGORY(fc) == ucp_Z) == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								                RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_WORD:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int category;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM215);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            category = UCD_CATEGORY(fc);
							 | 
						||
| 
								 | 
							
								            if ((category == ucp_L ||
							 | 
						||
| 
								 | 
							
								                 category == ucp_N ||
							 | 
						||
| 
								 | 
							
								                 fc == CHAR_UNDERSCORE) == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_CLIST:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            const uint32_t *cp;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM216);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            cp = PRIV(ucd_caseless_sets) + Lpropvalue;
							 | 
						||
| 
								 | 
							
								            for (;;)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (fc < *cp)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                if (Lctype == OP_NOTPROP) break;
							 | 
						||
| 
								 | 
							
								                RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								              if (fc == *cp++)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_UCNC:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM217);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT ||
							 | 
						||
| 
								 | 
							
								                 fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) ||
							 | 
						||
| 
								 | 
							
								                 fc >= 0xe000) == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_BIDICL:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM224);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            if ((UCD_BIDICLASS(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_BOOL:
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            BOOL ok;
							 | 
						||
| 
								 | 
							
								            const ucd_record *prop;
							 | 
						||
| 
								 | 
							
								            RMATCH(Fecode, RM223);
							 | 
						||
| 
								 | 
							
								            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								            if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            prop = GET_UCD(fc);
							 | 
						||
| 
								 | 
							
								            ok = MAPBIT(PRIV(ucd_boolprop_sets) +
							 | 
						||
| 
								 | 
							
								              UCD_BPROPS_PROP(prop), Lpropvalue) != 0;
							 | 
						||
| 
								 | 
							
								            if (ok == (Lctype == OP_NOTPROP))
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* This should never occur */
							 | 
						||
| 
								 | 
							
								          default:
							 | 
						||
| 
								 | 
							
								          return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Match extended Unicode sequences. We will get here only if the
							 | 
						||
| 
								 | 
							
								      support is in the binary; otherwise a compile-time error occurs. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else if (Lctype == OP_EXTUNI)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM218);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject,
							 | 
						||
| 
								 | 
							
								              utf, NULL);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          CHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif     /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* UTF mode for non-property testing character types. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (utf)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM219);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (Lctype == OP_ANY && IS_NEWLINE(Feptr)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          GETCHARINC(fc, Feptr);
							 | 
						||
| 
								 | 
							
								          switch(Lctype)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            case OP_ANY:               /* This is the non-NL case */
							 | 
						||
| 
								 | 
							
								            if (mb->partial != 0 &&    /* Take care with CRLF partial */
							 | 
						||
| 
								 | 
							
								                Feptr >= mb->end_subject &&
							 | 
						||
| 
								 | 
							
								                NLBLOCK->nltype == NLTYPE_FIXED &&
							 | 
						||
| 
								 | 
							
								                NLBLOCK->nllen == 2 &&
							 | 
						||
| 
								 | 
							
								                fc == NLBLOCK->nl[0])
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								              if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_ALLANY:
							 | 
						||
| 
								 | 
							
								            case OP_ANYBYTE:
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_ANYNL:
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              case CHAR_CR:
							 | 
						||
| 
								 | 
							
								              if (Feptr < mb->end_subject && UCHAR21(Feptr) == CHAR_LF) Feptr++;
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              case CHAR_LF:
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              case CHAR_VT:
							 | 
						||
| 
								 | 
							
								              case CHAR_FF:
							 | 
						||
| 
								 | 
							
								              case CHAR_NEL:
							 | 
						||
| 
								 | 
							
								#ifndef EBCDIC
							 | 
						||
| 
								 | 
							
								              case 0x2028:
							 | 
						||
| 
								 | 
							
								              case 0x2029:
							 | 
						||
| 
								 | 
							
								#endif  /* Not EBCDIC */
							 | 
						||
| 
								 | 
							
								              if (mb->bsr_convention == PCRE2_BSR_ANYCRLF)
							 | 
						||
| 
								 | 
							
								                RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_NOT_HSPACE:
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              HSPACE_CASES: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              default: break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_HSPACE:
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              HSPACE_CASES: break;
							 | 
						||
| 
								 | 
							
								              default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_NOT_VSPACE:
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              VSPACE_CASES: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              default: break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_VSPACE:
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              VSPACE_CASES: break;
							 | 
						||
| 
								 | 
							
								              default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_NOT_DIGIT:
							 | 
						||
| 
								 | 
							
								            if (fc < 256 && (mb->ctypes[fc] & ctype_digit) != 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_DIGIT:
							 | 
						||
| 
								 | 
							
								            if (fc >= 256 || (mb->ctypes[fc] & ctype_digit) == 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_NOT_WHITESPACE:
							 | 
						||
| 
								 | 
							
								            if (fc < 256 && (mb->ctypes[fc] & ctype_space) != 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_WHITESPACE:
							 | 
						||
| 
								 | 
							
								            if (fc >= 256 || (mb->ctypes[fc] & ctype_space) == 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_NOT_WORDCHAR:
							 | 
						||
| 
								 | 
							
								            if (fc < 256 && (mb->ctypes[fc] & ctype_word) != 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_WORDCHAR:
							 | 
						||
| 
								 | 
							
								            if (fc >= 256 || (mb->ctypes[fc] & ctype_word) == 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            default:
							 | 
						||
| 
								 | 
							
								            return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM33);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          if (Lctype == OP_ANY && IS_NEWLINE(Feptr))
							 | 
						||
| 
								 | 
							
								            RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          fc = *Feptr++;
							 | 
						||
| 
								 | 
							
								          switch(Lctype)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            case OP_ANY:               /* This is the non-NL case */
							 | 
						||
| 
								 | 
							
								            if (mb->partial != 0 &&    /* Take care with CRLF partial */
							 | 
						||
| 
								 | 
							
								                Feptr >= mb->end_subject &&
							 | 
						||
| 
								 | 
							
								                NLBLOCK->nltype == NLTYPE_FIXED &&
							 | 
						||
| 
								 | 
							
								                NLBLOCK->nllen == 2 &&
							 | 
						||
| 
								 | 
							
								                fc == NLBLOCK->nl[0])
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								              if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_ALLANY:
							 | 
						||
| 
								 | 
							
								            case OP_ANYBYTE:
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_ANYNL:
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              case CHAR_CR:
							 | 
						||
| 
								 | 
							
								              if (Feptr < mb->end_subject && *Feptr == CHAR_LF) Feptr++;
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              case CHAR_LF:
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              case CHAR_VT:
							 | 
						||
| 
								 | 
							
								              case CHAR_FF:
							 | 
						||
| 
								 | 
							
								              case CHAR_NEL:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								              case 0x2028:
							 | 
						||
| 
								 | 
							
								              case 0x2029:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								              if (mb->bsr_convention == PCRE2_BSR_ANYCRLF)
							 | 
						||
| 
								 | 
							
								                RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_NOT_HSPACE:
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              default: break;
							 | 
						||
| 
								 | 
							
								              HSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								              HSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_HSPACE:
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              HSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								              HSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_NOT_VSPACE:
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              default: break;
							 | 
						||
| 
								 | 
							
								              VSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								              VSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_VSPACE:
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              default: RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								              VSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								              VSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_NOT_DIGIT:
							 | 
						||
| 
								 | 
							
								            if (MAX_255(fc) && (mb->ctypes[fc] & ctype_digit) != 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_DIGIT:
							 | 
						||
| 
								 | 
							
								            if (!MAX_255(fc) || (mb->ctypes[fc] & ctype_digit) == 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_NOT_WHITESPACE:
							 | 
						||
| 
								 | 
							
								            if (MAX_255(fc) && (mb->ctypes[fc] & ctype_space) != 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_WHITESPACE:
							 | 
						||
| 
								 | 
							
								            if (!MAX_255(fc) || (mb->ctypes[fc] & ctype_space) == 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_NOT_WORDCHAR:
							 | 
						||
| 
								 | 
							
								            if (MAX_255(fc) && (mb->ctypes[fc] & ctype_word) != 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case OP_WORDCHAR:
							 | 
						||
| 
								 | 
							
								            if (!MAX_255(fc) || (mb->ctypes[fc] & ctype_word) == 0)
							 | 
						||
| 
								 | 
							
								              RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            default:
							 | 
						||
| 
								 | 
							
								            return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      /* Control never gets here */
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If maximizing, it is worth using inline code for speed, doing the type
							 | 
						||
| 
								 | 
							
								    test once at the start (i.e. keep it out of the loops). Once again,
							 | 
						||
| 
								 | 
							
								    "notmatch" can be an ordinary local variable because the loops do not call
							 | 
						||
| 
								 | 
							
								    RMATCH. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Lstart_eptr = Feptr;  /* Remember where we started */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (proptype >= 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        BOOL notmatch = Lctype == OP_NOTPROP;
							 | 
						||
| 
								 | 
							
								        switch(proptype)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          case PT_ANY:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (notmatch) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_LAMP:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int chartype;
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            chartype = UCD_CHARTYPE(fc);
							 | 
						||
| 
								 | 
							
								            if ((chartype == ucp_Lu ||
							 | 
						||
| 
								 | 
							
								                 chartype == ucp_Ll ||
							 | 
						||
| 
								 | 
							
								                 chartype == ucp_Lt) == notmatch)
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_GC:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if ((UCD_CATEGORY(fc) == Lpropvalue) == notmatch) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_PC:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if ((UCD_CHARTYPE(fc) == Lpropvalue) == notmatch) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_SC:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if ((UCD_SCRIPT(fc) == Lpropvalue) == notmatch) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_SCX:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            BOOL ok;
							 | 
						||
| 
								 | 
							
								            const ucd_record *prop;
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            prop = GET_UCD(fc);
							 | 
						||
| 
								 | 
							
								            ok = (prop->script == Lpropvalue ||
							 | 
						||
| 
								 | 
							
								                  MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), Lpropvalue) != 0);
							 | 
						||
| 
								 | 
							
								            if (ok == notmatch) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_ALNUM:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int category;
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            category = UCD_CATEGORY(fc);
							 | 
						||
| 
								 | 
							
								            if ((category == ucp_L || category == ucp_N) == notmatch)
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* Perl space used to exclude VT, but from Perl 5.18 it is included,
							 | 
						||
| 
								 | 
							
								          which means that Perl space and POSIX space are now identical. PCRE
							 | 
						||
| 
								 | 
							
								          was changed at release 8.34. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_SPACE:    /* Perl space */
							 | 
						||
| 
								 | 
							
								          case PT_PXSPACE:  /* POSIX space */
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              HSPACE_CASES:
							 | 
						||
| 
								 | 
							
								              VSPACE_CASES:
							 | 
						||
| 
								 | 
							
								              if (notmatch) goto ENDLOOP99;  /* Break the loop */
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              default:
							 | 
						||
| 
								 | 
							
								              if ((UCD_CATEGORY(fc) == ucp_Z) == notmatch)
							 | 
						||
| 
								 | 
							
								                goto ENDLOOP99;   /* Break the loop */
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          ENDLOOP99:
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_WORD:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int category;
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            category = UCD_CATEGORY(fc);
							 | 
						||
| 
								 | 
							
								            if ((category == ucp_L || category == ucp_N ||
							 | 
						||
| 
								 | 
							
								                 fc == CHAR_UNDERSCORE) == notmatch)
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_CLIST:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            const uint32_t *cp;
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            cp = PRIV(ucd_caseless_sets) + Lpropvalue;
							 | 
						||
| 
								 | 
							
								            for (;;)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (fc < *cp)
							 | 
						||
| 
								 | 
							
								                { if (notmatch) break; else goto GOT_MAX; }
							 | 
						||
| 
								 | 
							
								              if (fc == *cp++)
							 | 
						||
| 
								 | 
							
								                { if (notmatch) goto GOT_MAX; else break; }
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            Feptr += len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          GOT_MAX:
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_UCNC:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT ||
							 | 
						||
| 
								 | 
							
								                 fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) ||
							 | 
						||
| 
								 | 
							
								                 fc >= 0xe000) == notmatch)
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            Feptr += len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_BIDICL:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if ((UCD_BIDICLASS(fc) == Lpropvalue) == notmatch) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case PT_BOOL:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            BOOL ok;
							 | 
						||
| 
								 | 
							
								            const ucd_record *prop;
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLENTEST(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            prop = GET_UCD(fc);
							 | 
						||
| 
								 | 
							
								            ok = MAPBIT(PRIV(ucd_boolprop_sets) +
							 | 
						||
| 
								 | 
							
								              UCD_BPROPS_PROP(prop), Lpropvalue) != 0;
							 | 
						||
| 
								 | 
							
								            if (ok == notmatch) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          default:
							 | 
						||
| 
								 | 
							
								          return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* Feptr is now past the end of the maximum run */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (reptype == REPTYPE_POS) continue;    /* No backtracking */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* After \C in UTF mode, Lstart_eptr might be in the middle of a
							 | 
						||
| 
								 | 
							
								        Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't
							 | 
						||
| 
								 | 
							
								        go too far. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for(;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr <= Lstart_eptr) break;
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM222);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          Feptr--;
							 | 
						||
| 
								 | 
							
								          if (utf) BACKCHAR(Feptr);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Match extended Unicode grapheme clusters. We will get here only if the
							 | 
						||
| 
								 | 
							
								      support is in the binary; otherwise a compile-time error occurs. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else if (Lctype == OP_EXTUNI)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            GETCHARINCTEST(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject,
							 | 
						||
| 
								 | 
							
								              utf, NULL);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          CHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* Feptr is now past the end of the maximum run */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (reptype == REPTYPE_POS) continue;    /* No backtracking */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* We use <= Lstart_eptr rather than == Lstart_eptr to detect the start
							 | 
						||
| 
								 | 
							
								        of the run while backtracking because the use of \C in UTF mode can
							 | 
						||
| 
								 | 
							
								        cause BACKCHAR to move back past Lstart_eptr. This is just palliative;
							 | 
						||
| 
								 | 
							
								        the use of \C in UTF mode is fraught with danger. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for(;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          int lgb, rgb;
							 | 
						||
| 
								 | 
							
								          PCRE2_SPTR fptr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (Feptr <= Lstart_eptr) break;   /* At start of char run */
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM220);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* Backtracking over an extended grapheme cluster involves inspecting
							 | 
						||
| 
								 | 
							
								          the previous two characters (if present) to see if a break is
							 | 
						||
| 
								 | 
							
								          permitted between them. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          Feptr--;
							 | 
						||
| 
								 | 
							
								          if (!utf) fc = *Feptr; else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            BACKCHAR(Feptr);
							 | 
						||
| 
								 | 
							
								            GETCHAR(fc, Feptr);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          rgb = UCD_GRAPHBREAK(fc);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          for (;;)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr <= Lstart_eptr) break;   /* At start of char run */
							 | 
						||
| 
								 | 
							
								            fptr = Feptr - 1;
							 | 
						||
| 
								 | 
							
								            if (!utf) fc = *fptr; else
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              BACKCHAR(fptr);
							 | 
						||
| 
								 | 
							
								              GETCHAR(fc, fptr);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            lgb = UCD_GRAPHBREAK(fc);
							 | 
						||
| 
								 | 
							
								            if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
							 | 
						||
| 
								 | 
							
								            Feptr = fptr;
							 | 
						||
| 
								 | 
							
								            rgb = lgb;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif   /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (utf)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        switch(Lctype)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          case OP_ANY:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (IS_NEWLINE(Feptr)) break;
							 | 
						||
| 
								 | 
							
								            if (mb->partial != 0 &&    /* Take care with CRLF partial */
							 | 
						||
| 
								 | 
							
								                Feptr + 1 >= mb->end_subject &&
							 | 
						||
| 
								 | 
							
								                NLBLOCK->nltype == NLTYPE_FIXED &&
							 | 
						||
| 
								 | 
							
								                NLBLOCK->nllen == 2 &&
							 | 
						||
| 
								 | 
							
								                UCHAR21(Feptr) == NLBLOCK->nl[0])
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								              if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_ALLANY:
							 | 
						||
| 
								 | 
							
								          if (Lmax < UINT32_MAX)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								              Feptr++;
							 | 
						||
| 
								 | 
							
								              ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            Feptr = mb->end_subject;   /* Unlimited UTF-8 repeat */
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* The "byte" (i.e. "code unit") case is the same as non-UTF */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_ANYBYTE:
							 | 
						||
| 
								 | 
							
								          fc = Lmax - Lmin;
							 | 
						||
| 
								 | 
							
								          if (fc > (uint32_t)(mb->end_subject - Feptr))
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            Feptr = mb->end_subject;
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          else Feptr += fc;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_ANYNL:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (fc == CHAR_CR)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (++Feptr >= mb->end_subject) break;
							 | 
						||
| 
								 | 
							
								              if (UCHAR21(Feptr) == CHAR_LF) Feptr++;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (fc != CHAR_LF &&
							 | 
						||
| 
								 | 
							
								                  (mb->bsr_convention == PCRE2_BSR_ANYCRLF ||
							 | 
						||
| 
								 | 
							
								                   (fc != CHAR_VT && fc != CHAR_FF && fc != CHAR_NEL
							 | 
						||
| 
								 | 
							
								#ifndef EBCDIC
							 | 
						||
| 
								 | 
							
								                    && fc != 0x2028 && fc != 0x2029
							 | 
						||
| 
								 | 
							
								#endif  /* Not EBCDIC */
							 | 
						||
| 
								 | 
							
								                    )))
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								              Feptr += len;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_NOT_HSPACE:
							 | 
						||
| 
								 | 
							
								          case OP_HSPACE:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            BOOL gotspace;
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              HSPACE_CASES: gotspace = TRUE; break;
							 | 
						||
| 
								 | 
							
								              default: gotspace = FALSE; break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (gotspace == (Lctype == OP_NOT_HSPACE)) break;
							 | 
						||
| 
								 | 
							
								            Feptr += len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_NOT_VSPACE:
							 | 
						||
| 
								 | 
							
								          case OP_VSPACE:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            BOOL gotspace;
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            switch(fc)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              VSPACE_CASES: gotspace = TRUE; break;
							 | 
						||
| 
								 | 
							
								              default: gotspace = FALSE; break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (gotspace == (Lctype == OP_NOT_VSPACE)) break;
							 | 
						||
| 
								 | 
							
								            Feptr += len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_NOT_DIGIT:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (fc < 256 && (mb->ctypes[fc] & ctype_digit) != 0) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_DIGIT:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (fc >= 256 ||(mb->ctypes[fc] & ctype_digit) == 0) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_NOT_WHITESPACE:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (fc < 256 && (mb->ctypes[fc] & ctype_space) != 0) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_WHITESPACE:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (fc >= 256 ||(mb->ctypes[fc] & ctype_space) == 0) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_NOT_WORDCHAR:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (fc < 256 && (mb->ctypes[fc] & ctype_word) != 0) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_WORDCHAR:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            int len = 1;
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            GETCHARLEN(fc, Feptr, len);
							 | 
						||
| 
								 | 
							
								            if (fc >= 256 || (mb->ctypes[fc] & ctype_word) == 0) break;
							 | 
						||
| 
								 | 
							
								            Feptr+= len;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          default:
							 | 
						||
| 
								 | 
							
								          return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (reptype == REPTYPE_POS) continue;    /* No backtracking */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* After \C in UTF mode, Lstart_eptr might be in the middle of a
							 | 
						||
| 
								 | 
							
								        Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't go
							 | 
						||
| 
								 | 
							
								        too far. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for(;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr <= Lstart_eptr) break;
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM221);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          Feptr--;
							 | 
						||
| 
								 | 
							
								          BACKCHAR(Feptr);
							 | 
						||
| 
								 | 
							
								          if (Lctype == OP_ANYNL && Feptr > Lstart_eptr &&
							 | 
						||
| 
								 | 
							
								              UCHAR21(Feptr) == CHAR_NL && UCHAR21(Feptr - 1) == CHAR_CR)
							 | 
						||
| 
								 | 
							
								            Feptr--;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Not UTF mode */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        switch(Lctype)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          case OP_ANY:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (IS_NEWLINE(Feptr)) break;
							 | 
						||
| 
								 | 
							
								            if (mb->partial != 0 &&    /* Take care with CRLF partial */
							 | 
						||
| 
								 | 
							
								                Feptr + 1 >= mb->end_subject &&
							 | 
						||
| 
								 | 
							
								                NLBLOCK->nltype == NLTYPE_FIXED &&
							 | 
						||
| 
								 | 
							
								                NLBLOCK->nllen == 2 &&
							 | 
						||
| 
								 | 
							
								                *Feptr == NLBLOCK->nl[0])
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								              if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_ALLANY:
							 | 
						||
| 
								 | 
							
								          case OP_ANYBYTE:
							 | 
						||
| 
								 | 
							
								          fc = Lmax - Lmin;
							 | 
						||
| 
								 | 
							
								          if (fc > (uint32_t)(mb->end_subject - Feptr))
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            Feptr = mb->end_subject;
							 | 
						||
| 
								 | 
							
								            SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          else Feptr += fc;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_ANYNL:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            fc = *Feptr;
							 | 
						||
| 
								 | 
							
								            if (fc == CHAR_CR)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (++Feptr >= mb->end_subject) break;
							 | 
						||
| 
								 | 
							
								              if (*Feptr == CHAR_LF) Feptr++;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (fc != CHAR_LF && (mb->bsr_convention == PCRE2_BSR_ANYCRLF ||
							 | 
						||
| 
								 | 
							
								                 (fc != CHAR_VT && fc != CHAR_FF && fc != CHAR_NEL
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								                 && fc != 0x2028 && fc != 0x2029
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								                 ))) break;
							 | 
						||
| 
								 | 
							
								              Feptr++;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_NOT_HSPACE:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            switch(*Feptr)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              default: Feptr++; break;
							 | 
						||
| 
								 | 
							
								              HSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								              HSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								              goto ENDLOOP00;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          ENDLOOP00:
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_HSPACE:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            switch(*Feptr)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              default: goto ENDLOOP01;
							 | 
						||
| 
								 | 
							
								              HSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								              HSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								              Feptr++; break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          ENDLOOP01:
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_NOT_VSPACE:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            switch(*Feptr)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              default: Feptr++; break;
							 | 
						||
| 
								 | 
							
								              VSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								              VSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								              goto ENDLOOP02;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          ENDLOOP02:
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_VSPACE:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            switch(*Feptr)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              default: goto ENDLOOP03;
							 | 
						||
| 
								 | 
							
								              VSPACE_BYTE_CASES:
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								              VSPACE_MULTIBYTE_CASES:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								              Feptr++; break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          ENDLOOP03:
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_NOT_DIGIT:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_digit) != 0)
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_DIGIT:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_digit) == 0)
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_NOT_WHITESPACE:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_space) != 0)
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_WHITESPACE:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_space) == 0)
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_NOT_WORDCHAR:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_word) != 0)
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case OP_WORDCHAR:
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_word) == 0)
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            Feptr++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          default:
							 | 
						||
| 
								 | 
							
								          return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (reptype == REPTYPE_POS) continue;    /* No backtracking */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr == Lstart_eptr) break;
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM34);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          Feptr--;
							 | 
						||
| 
								 | 
							
								          if (Lctype == OP_ANYNL && Feptr > Lstart_eptr && *Feptr == CHAR_LF &&
							 | 
						||
| 
								 | 
							
								              Feptr[-1] == CHAR_CR) Feptr--;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;  /* End of repeat character type processing */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lstart_eptr
							 | 
						||
| 
								 | 
							
								#undef Lmin
							 | 
						||
| 
								 | 
							
								#undef Lmax
							 | 
						||
| 
								 | 
							
								#undef Lctype
							 | 
						||
| 
								 | 
							
								#undef Lpropvalue
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Match a back reference, possibly repeatedly. Look past the end of the
							 | 
						||
| 
								 | 
							
								    item to see if there is repeat information following. The OP_REF and
							 | 
						||
| 
								 | 
							
								    OP_REFI opcodes are used for a reference to a numbered group or to a
							 | 
						||
| 
								 | 
							
								    non-duplicated named group. For a duplicated named group, OP_DNREF and
							 | 
						||
| 
								 | 
							
								    OP_DNREFI are used. In this case we must scan the list of groups to which
							 | 
						||
| 
								 | 
							
								    the name refers, and use the first one that is set. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lmin      F->temp_32[0]
							 | 
						||
| 
								 | 
							
								#define Lmax      F->temp_32[1]
							 | 
						||
| 
								 | 
							
								#define Lcaseless F->temp_32[2]
							 | 
						||
| 
								 | 
							
								#define Lstart    F->temp_sptr[0]
							 | 
						||
| 
								 | 
							
								#define Loffset   F->temp_size
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_DNREF:
							 | 
						||
| 
								 | 
							
								    case OP_DNREFI:
							 | 
						||
| 
								 | 
							
								    Lcaseless = (Fop == OP_DNREFI);
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      int count = GET2(Fecode, 1+IMM2_SIZE);
							 | 
						||
| 
								 | 
							
								      PCRE2_SPTR slot = mb->name_table + GET2(Fecode, 1) * mb->name_entry_size;
							 | 
						||
| 
								 | 
							
								      Fecode += 1 + 2*IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      while (count-- > 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        Loffset = (GET2(slot, 0) << 1) - 2;
							 | 
						||
| 
								 | 
							
								        if (Loffset < Foffset_top && Fovector[Loffset] != PCRE2_UNSET) break;
							 | 
						||
| 
								 | 
							
								        slot += mb->name_entry_size;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    goto REF_REPEAT;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_REF:
							 | 
						||
| 
								 | 
							
								    case OP_REFI:
							 | 
						||
| 
								 | 
							
								    Lcaseless = (Fop == OP_REFI);
							 | 
						||
| 
								 | 
							
								    Loffset = (GET2(Fecode, 1) << 1) - 2;
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Set up for repetition, or handle the non-repeated case. The maximum and
							 | 
						||
| 
								 | 
							
								    minimum must be in the heap frame, but as they are short-term values, we
							 | 
						||
| 
								 | 
							
								    use temporary fields. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    REF_REPEAT:
							 | 
						||
| 
								 | 
							
								    switch (*Fecode)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      case OP_CRSTAR:
							 | 
						||
| 
								 | 
							
								      case OP_CRMINSTAR:
							 | 
						||
| 
								 | 
							
								      case OP_CRPLUS:
							 | 
						||
| 
								 | 
							
								      case OP_CRMINPLUS:
							 | 
						||
| 
								 | 
							
								      case OP_CRQUERY:
							 | 
						||
| 
								 | 
							
								      case OP_CRMINQUERY:
							 | 
						||
| 
								 | 
							
								      fc = *Fecode++ - OP_CRSTAR;
							 | 
						||
| 
								 | 
							
								      Lmin = rep_min[fc];
							 | 
						||
| 
								 | 
							
								      Lmax = rep_max[fc];
							 | 
						||
| 
								 | 
							
								      reptype = rep_typ[fc];
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_CRRANGE:
							 | 
						||
| 
								 | 
							
								      case OP_CRMINRANGE:
							 | 
						||
| 
								 | 
							
								      Lmin = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								      Lmax = GET2(Fecode, 1 + IMM2_SIZE);
							 | 
						||
| 
								 | 
							
								      reptype = rep_typ[*Fecode - OP_CRSTAR];
							 | 
						||
| 
								 | 
							
								      if (Lmax == 0) Lmax = UINT32_MAX;  /* Max 0 => infinity */
							 | 
						||
| 
								 | 
							
								      Fecode += 1 + 2 * IMM2_SIZE;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      default:                  /* No repeat follows */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        rrc = match_ref(Loffset, Lcaseless, F, mb, &length);
							 | 
						||
| 
								 | 
							
								        if (rrc != 0)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (rrc > 0) Feptr = mb->end_subject;   /* Partial match */
							 | 
						||
| 
								 | 
							
								          CHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      Feptr += length;
							 | 
						||
| 
								 | 
							
								      continue;              /* With the main loop */
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Handle repeated back references. If a set group has length zero, just
							 | 
						||
| 
								 | 
							
								    continue with the main loop, because it matches however many times. For an
							 | 
						||
| 
								 | 
							
								    unset reference, if the minimum is zero, we can also just continue. We can
							 | 
						||
| 
								 | 
							
								    also continue if PCRE2_MATCH_UNSET_BACKREF is set, because this makes unset
							 | 
						||
| 
								 | 
							
								    group behave as a zero-length group. For any other unset cases, carrying
							 | 
						||
| 
								 | 
							
								    on will result in NOMATCH. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Loffset < Foffset_top && Fovector[Loffset] != PCRE2_UNSET)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (Fovector[Loffset] == Fovector[Loffset + 1]) continue;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else  /* Group is not set */
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (Lmin == 0 || (mb->poptions & PCRE2_MATCH_UNSET_BACKREF) != 0)
							 | 
						||
| 
								 | 
							
								        continue;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* First, ensure the minimum number of matches are present. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (i = 1; i <= Lmin; i++)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      PCRE2_SIZE slength;
							 | 
						||
| 
								 | 
							
								      rrc = match_ref(Loffset, Lcaseless, F, mb, &slength);
							 | 
						||
| 
								 | 
							
								      if (rrc != 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (rrc > 0) Feptr = mb->end_subject;   /* Partial match */
							 | 
						||
| 
								 | 
							
								        CHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								        RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      Feptr += slength;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If min = max, we are done. They are not both allowed to be zero. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Lmin == Lmax) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If minimizing, keep trying and advancing the pointer. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (reptype == REPTYPE_MIN)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      for (;;)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        PCRE2_SIZE slength;
							 | 
						||
| 
								 | 
							
								        RMATCH(Fecode, RM20);
							 | 
						||
| 
								 | 
							
								        if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								        if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        rrc = match_ref(Loffset, Lcaseless, F, mb, &slength);
							 | 
						||
| 
								 | 
							
								        if (rrc != 0)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (rrc > 0) Feptr = mb->end_subject;   /* Partial match */
							 | 
						||
| 
								 | 
							
								          CHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								          RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        Feptr += slength;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      /* Control never gets here */
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If maximizing, find the longest string and work backwards, as long as
							 | 
						||
| 
								 | 
							
								    the matched lengths for each iteration are the same. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      BOOL samelengths = TRUE;
							 | 
						||
| 
								 | 
							
								      Lstart = Feptr;     /* Starting position */
							 | 
						||
| 
								 | 
							
								      Flength = Fovector[Loffset+1] - Fovector[Loffset];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        PCRE2_SIZE slength;
							 | 
						||
| 
								 | 
							
								        rrc = match_ref(Loffset, Lcaseless, F, mb, &slength);
							 | 
						||
| 
								 | 
							
								        if (rrc != 0)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          /* Can't use CHECK_PARTIAL because we don't want to update Feptr in
							 | 
						||
| 
								 | 
							
								          the soft partial matching case. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (rrc > 0 && mb->partial != 0 &&
							 | 
						||
| 
								 | 
							
								              mb->end_subject > mb->start_used_ptr)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								            if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (slength != Flength) samelengths = FALSE;
							 | 
						||
| 
								 | 
							
								        Feptr += slength;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If the length matched for each repetition is the same as the length of
							 | 
						||
| 
								 | 
							
								      the captured group, we can easily work backwards. This is the normal
							 | 
						||
| 
								 | 
							
								      case. However, in caseless UTF-8 mode there are pairs of case-equivalent
							 | 
						||
| 
								 | 
							
								      characters whose lengths (in terms of code units) differ. However, this
							 | 
						||
| 
								 | 
							
								      is very rare, so we handle it by re-matching fewer and fewer times. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (samelengths)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        while (Feptr >= Lstart)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM21);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          Feptr -= Flength;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* The rare case of non-matching lengths. Re-scan the repetition for each
							 | 
						||
| 
								 | 
							
								      iteration. We know that match_ref() will succeed every time. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        Lmax = i;
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          RMATCH(Fecode, RM22);
							 | 
						||
| 
								 | 
							
								          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          if (Feptr == Lstart) break; /* Failed after minimal repetition */
							 | 
						||
| 
								 | 
							
								          Feptr = Lstart;
							 | 
						||
| 
								 | 
							
								          Lmax--;
							 | 
						||
| 
								 | 
							
								          for (i = Lmin; i < Lmax; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            PCRE2_SIZE slength;
							 | 
						||
| 
								 | 
							
								            (void)match_ref(Loffset, Lcaseless, F, mb, &slength);
							 | 
						||
| 
								 | 
							
								            Feptr += slength;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    /* Control never gets here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lcaseless
							 | 
						||
| 
								 | 
							
								#undef Lmin
							 | 
						||
| 
								 | 
							
								#undef Lmax
							 | 
						||
| 
								 | 
							
								#undef Lstart
							 | 
						||
| 
								 | 
							
								#undef Loffset
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ========================================================================= */
							 | 
						||
| 
								 | 
							
								/*           Opcodes for the start of various parenthesized items            */
							 | 
						||
| 
								 | 
							
								/* ========================================================================= */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* In all cases, if the result of RMATCH() is MATCH_THEN, check whether the
							 | 
						||
| 
								 | 
							
								    (*THEN) is within the current branch by comparing the address of OP_THEN
							 | 
						||
| 
								 | 
							
								    that is passed back with the end of the branch. If (*THEN) is within the
							 | 
						||
| 
								 | 
							
								    current branch, and the branch is one of two or more alternatives (it
							 | 
						||
| 
								 | 
							
								    either starts or ends with OP_ALT), we have reached the limit of THEN's
							 | 
						||
| 
								 | 
							
								    action, so convert the return code to NOMATCH, which will cause normal
							 | 
						||
| 
								 | 
							
								    backtracking to happen from now on. Otherwise, THEN is passed back to an
							 | 
						||
| 
								 | 
							
								    outer alternative. This implements Perl's treatment of parenthesized
							 | 
						||
| 
								 | 
							
								    groups, where a group not containing | does not affect the current
							 | 
						||
| 
								 | 
							
								    alternative, that is, (X) is NOT the same as (X|(*F)). */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* BRAZERO, BRAMINZERO and SKIPZERO occur just before a non-possessive
							 | 
						||
| 
								 | 
							
								    bracket group, indicating that it may occur zero times. It may repeat
							 | 
						||
| 
								 | 
							
								    infinitely, or not at all - i.e. it could be ()* or ()? or even (){0} in
							 | 
						||
| 
								 | 
							
								    the pattern. Brackets with fixed upper repeat limits are compiled as a
							 | 
						||
| 
								 | 
							
								    number of copies, with the optional ones preceded by BRAZERO or BRAMINZERO.
							 | 
						||
| 
								 | 
							
								    Possessive groups with possible zero repeats are preceded by BRAPOSZERO. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lnext_ecode F->temp_sptr[0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_BRAZERO:
							 | 
						||
| 
								 | 
							
								    Lnext_ecode = Fecode + 1;
							 | 
						||
| 
								 | 
							
								    RMATCH(Lnext_ecode, RM9);
							 | 
						||
| 
								 | 
							
								    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								    do Lnext_ecode += GET(Lnext_ecode, 1); while (*Lnext_ecode == OP_ALT);
							 | 
						||
| 
								 | 
							
								    Fecode = Lnext_ecode + 1 + LINK_SIZE;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_BRAMINZERO:
							 | 
						||
| 
								 | 
							
								    Lnext_ecode = Fecode + 1;
							 | 
						||
| 
								 | 
							
								    do Lnext_ecode += GET(Lnext_ecode, 1); while (*Lnext_ecode == OP_ALT);
							 | 
						||
| 
								 | 
							
								    RMATCH(Lnext_ecode + 1 + LINK_SIZE, RM10);
							 | 
						||
| 
								 | 
							
								    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lnext_ecode
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_SKIPZERO:
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    do Fecode += GET(Fecode,1); while (*Fecode == OP_ALT);
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + LINK_SIZE;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Handle possessive brackets with an unlimited repeat. The end of these
							 | 
						||
| 
								 | 
							
								    brackets will always be OP_KETRPOS, which returns MATCH_KETRPOS without
							 | 
						||
| 
								 | 
							
								    going further in the pattern. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lframe_type    F->temp_32[0]
							 | 
						||
| 
								 | 
							
								#define Lmatched_once  F->temp_32[1]
							 | 
						||
| 
								 | 
							
								#define Lzero_allowed  F->temp_32[2]
							 | 
						||
| 
								 | 
							
								#define Lstart_eptr    F->temp_sptr[0]
							 | 
						||
| 
								 | 
							
								#define Lstart_group   F->temp_sptr[1]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_BRAPOSZERO:
							 | 
						||
| 
								 | 
							
								    Lzero_allowed = TRUE;                /* Zero repeat is allowed */
							 | 
						||
| 
								 | 
							
								    Fecode += 1;
							 | 
						||
| 
								 | 
							
								    if (*Fecode == OP_CBRAPOS || *Fecode == OP_SCBRAPOS)
							 | 
						||
| 
								 | 
							
								      goto POSSESSIVE_CAPTURE;
							 | 
						||
| 
								 | 
							
								    goto POSSESSIVE_NON_CAPTURE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_BRAPOS:
							 | 
						||
| 
								 | 
							
								    case OP_SBRAPOS:
							 | 
						||
| 
								 | 
							
								    Lzero_allowed = FALSE;               /* Zero repeat not allowed */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    POSSESSIVE_NON_CAPTURE:
							 | 
						||
| 
								 | 
							
								    Lframe_type = GF_NOCAPTURE;          /* Remembered frame type */
							 | 
						||
| 
								 | 
							
								    goto POSSESSIVE_GROUP;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_CBRAPOS:
							 | 
						||
| 
								 | 
							
								    case OP_SCBRAPOS:
							 | 
						||
| 
								 | 
							
								    Lzero_allowed = FALSE;               /* Zero repeat not allowed */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    POSSESSIVE_CAPTURE:
							 | 
						||
| 
								 | 
							
								    number = GET2(Fecode, 1+LINK_SIZE);
							 | 
						||
| 
								 | 
							
								    Lframe_type = GF_CAPTURE | number;   /* Remembered frame type */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    POSSESSIVE_GROUP:
							 | 
						||
| 
								 | 
							
								    Lmatched_once = FALSE;               /* Never matched */
							 | 
						||
| 
								 | 
							
								    Lstart_group = Fecode;               /* Start of this group */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (;;)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Lstart_eptr = Feptr;               /* Position at group start */
							 | 
						||
| 
								 | 
							
								      group_frame_type = Lframe_type;
							 | 
						||
| 
								 | 
							
								      RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM8);
							 | 
						||
| 
								 | 
							
								      if (rrc == MATCH_KETRPOS)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        Lmatched_once = TRUE;            /* Matched at least once */
							 | 
						||
| 
								 | 
							
								        if (Feptr == Lstart_eptr)        /* Empty match; skip to end */
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT);
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Fecode = Lstart_group;
							 | 
						||
| 
								 | 
							
								        continue;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* See comment above about handling THEN. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (rrc == MATCH_THEN)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        PCRE2_SPTR next_ecode = Fecode + GET(Fecode,1);
							 | 
						||
| 
								 | 
							
								        if (mb->verb_ecode_ptr < next_ecode &&
							 | 
						||
| 
								 | 
							
								            (*Fecode == OP_ALT || *next_ecode == OP_ALT))
							 | 
						||
| 
								 | 
							
								          rrc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								      Fecode += GET(Fecode, 1);
							 | 
						||
| 
								 | 
							
								      if (*Fecode != OP_ALT) break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Success if matched something or zero repeat allowed */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Lmatched_once || Lzero_allowed)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Fecode += 1 + LINK_SIZE;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lmatched_once
							 | 
						||
| 
								 | 
							
								#undef Lzero_allowed
							 | 
						||
| 
								 | 
							
								#undef Lframe_type
							 | 
						||
| 
								 | 
							
								#undef Lstart_eptr
							 | 
						||
| 
								 | 
							
								#undef Lstart_group
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Handle non-capturing brackets that cannot match an empty string. When we
							 | 
						||
| 
								 | 
							
								    get to the final alternative within the brackets, as long as there are no
							 | 
						||
| 
								 | 
							
								    THEN's in the pattern, we can optimize by not recording a new backtracking
							 | 
						||
| 
								 | 
							
								    point. (Ideally we should test for a THEN within this group, but we don't
							 | 
						||
| 
								 | 
							
								    have that information.) Don't do this if we are at the very top level,
							 | 
						||
| 
								 | 
							
								    however, because that would make handling assertions and once-only brackets
							 | 
						||
| 
								 | 
							
								    messier when there is nothing to go back to. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lframe_type F->temp_32[0]     /* Set for all that use GROUPLOOP */
							 | 
						||
| 
								 | 
							
								#define Lnext_branch F->temp_sptr[0]  /* Used only in OP_BRA handling */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_BRA:
							 | 
						||
| 
								 | 
							
								    if (mb->hasthen || Frdepth == 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Lframe_type = 0;
							 | 
						||
| 
								 | 
							
								      goto GROUPLOOP;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (;;)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Lnext_branch = Fecode + GET(Fecode, 1);
							 | 
						||
| 
								 | 
							
								      if (*Lnext_branch != OP_ALT) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* This is never the final branch. We do not need to test for MATCH_THEN
							 | 
						||
| 
								 | 
							
								      here because this code is not used when there is a THEN in the pattern. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM1);
							 | 
						||
| 
								 | 
							
								      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								      Fecode = Lnext_branch;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Hit the start of the final branch. Continue at this level. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Fecode += PRIV(OP_lengths)[*Fecode];
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lnext_branch
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Handle a capturing bracket, other than those that are possessive with an
							 | 
						||
| 
								 | 
							
								    unlimited repeat. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_CBRA:
							 | 
						||
| 
								 | 
							
								    case OP_SCBRA:
							 | 
						||
| 
								 | 
							
								    Lframe_type = GF_CAPTURE | GET2(Fecode, 1+LINK_SIZE);
							 | 
						||
| 
								 | 
							
								    goto GROUPLOOP;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Atomic groups and non-capturing brackets that can match an empty string
							 | 
						||
| 
								 | 
							
								    must record a backtracking point and also set up a chained frame. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_ONCE:
							 | 
						||
| 
								 | 
							
								    case OP_SCRIPT_RUN:
							 | 
						||
| 
								 | 
							
								    case OP_SBRA:
							 | 
						||
| 
								 | 
							
								    Lframe_type = GF_NOCAPTURE | Fop;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    GROUPLOOP:
							 | 
						||
| 
								 | 
							
								    for (;;)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      group_frame_type = Lframe_type;
							 | 
						||
| 
								 | 
							
								      RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM2);
							 | 
						||
| 
								 | 
							
								      if (rrc == MATCH_THEN)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        PCRE2_SPTR next_ecode = Fecode + GET(Fecode,1);
							 | 
						||
| 
								 | 
							
								        if (mb->verb_ecode_ptr < next_ecode &&
							 | 
						||
| 
								 | 
							
								            (*Fecode == OP_ALT || *next_ecode == OP_ALT))
							 | 
						||
| 
								 | 
							
								          rrc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								      Fecode += GET(Fecode, 1);
							 | 
						||
| 
								 | 
							
								      if (*Fecode != OP_ALT) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    /* Control never reaches here. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lframe_type
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Recursion either matches the current regex, or some subexpression. The
							 | 
						||
| 
								 | 
							
								    offset data is the offset to the starting bracket from the start of the
							 | 
						||
| 
								 | 
							
								    whole pattern. (This is so that it works from duplicated subpatterns.) */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lframe_type F->temp_32[0]
							 | 
						||
| 
								 | 
							
								#define Lstart_branch F->temp_sptr[0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_RECURSE:
							 | 
						||
| 
								 | 
							
								    bracode = mb->start_code + GET(Fecode, 1);
							 | 
						||
| 
								 | 
							
								    number = (bracode == mb->start_code)? 0 : GET2(bracode, 1 + LINK_SIZE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If we are already in a recursion, check for repeating the same one
							 | 
						||
| 
								 | 
							
								    without advancing the subject pointer. This should catch convoluted mutual
							 | 
						||
| 
								 | 
							
								    recursions. (Some simple cases are caught at compile time.) */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Fcurrent_recurse != RECURSE_UNSET)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      offset = Flast_group_offset;
							 | 
						||
| 
								 | 
							
								      while (offset != PCRE2_UNSET)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        N = (heapframe *)((char *)mb->match_frames + offset);
							 | 
						||
| 
								 | 
							
								        P = (heapframe *)((char *)N - frame_size);
							 | 
						||
| 
								 | 
							
								        if (N->group_frame_type == (GF_RECURSE | number))
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (Feptr == P->eptr) return PCRE2_ERROR_RECURSELOOP;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        offset = P->last_group_offset;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Now run the recursion, branch by branch. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Lstart_branch = bracode;
							 | 
						||
| 
								 | 
							
								    Lframe_type = GF_RECURSE | number;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (;;)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      PCRE2_SPTR next_ecode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      group_frame_type = Lframe_type;
							 | 
						||
| 
								 | 
							
								      RMATCH(Lstart_branch + PRIV(OP_lengths)[*Lstart_branch], RM11);
							 | 
						||
| 
								 | 
							
								      next_ecode = Lstart_branch + GET(Lstart_branch,1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Handle backtracking verbs, which are defined in a range that can
							 | 
						||
| 
								 | 
							
								      easily be tested for. PCRE does not allow THEN, SKIP, PRUNE or COMMIT to
							 | 
						||
| 
								 | 
							
								      escape beyond a recursion; they cause a NOMATCH for the entire recursion.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      When one of these verbs triggers, the current recursion group number is
							 | 
						||
| 
								 | 
							
								      recorded. If it matches the recursion we are processing, the verb
							 | 
						||
| 
								 | 
							
								      happened within the recursion and we must deal with it. Otherwise it must
							 | 
						||
| 
								 | 
							
								      have happened after the recursion completed, and so has to be passed
							 | 
						||
| 
								 | 
							
								      back. See comment above about handling THEN. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX &&
							 | 
						||
| 
								 | 
							
								          mb->verb_current_recurse == (Lframe_type ^ GF_RECURSE))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (rrc == MATCH_THEN && mb->verb_ecode_ptr < next_ecode &&
							 | 
						||
| 
								 | 
							
								            (*Lstart_branch == OP_ALT || *next_ecode == OP_ALT))
							 | 
						||
| 
								 | 
							
								          rrc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								        else RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Note that carrying on after (*ACCEPT) in a recursion is handled in the
							 | 
						||
| 
								 | 
							
								      OP_ACCEPT code. Nothing needs to be done here. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								      Lstart_branch = next_ecode;
							 | 
						||
| 
								 | 
							
								      if (*Lstart_branch != OP_ALT) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    /* Control never reaches here. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lframe_type
							 | 
						||
| 
								 | 
							
								#undef Lstart_branch
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Positive assertions are like other groups except that PCRE doesn't allow
							 | 
						||
| 
								 | 
							
								    the effect of (*THEN) to escape beyond an assertion; it is therefore
							 | 
						||
| 
								 | 
							
								    treated as NOMATCH. (*ACCEPT) is treated as successful assertion, with its
							 | 
						||
| 
								 | 
							
								    captures and mark retained. Any other return is an error. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lframe_type  F->temp_32[0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_ASSERT:
							 | 
						||
| 
								 | 
							
								    case OP_ASSERTBACK:
							 | 
						||
| 
								 | 
							
								    case OP_ASSERT_NA:
							 | 
						||
| 
								 | 
							
								    case OP_ASSERTBACK_NA:
							 | 
						||
| 
								 | 
							
								    Lframe_type = GF_NOCAPTURE | Fop;
							 | 
						||
| 
								 | 
							
								    for (;;)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      group_frame_type = Lframe_type;
							 | 
						||
| 
								 | 
							
								      RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM3);
							 | 
						||
| 
								 | 
							
								      if (rrc == MATCH_ACCEPT)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        memcpy(Fovector,
							 | 
						||
| 
								 | 
							
								              (char *)assert_accept_frame + offsetof(heapframe, ovector),
							 | 
						||
| 
								 | 
							
								              assert_accept_frame->offset_top * sizeof(PCRE2_SIZE));
							 | 
						||
| 
								 | 
							
								        Foffset_top = assert_accept_frame->offset_top;
							 | 
						||
| 
								 | 
							
								        Fmark = assert_accept_frame->mark;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								      Fecode += GET(Fecode, 1);
							 | 
						||
| 
								 | 
							
								      if (*Fecode != OP_ALT) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT);
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + LINK_SIZE;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lframe_type
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Handle negative assertions. Loop for each non-matching branch as for
							 | 
						||
| 
								 | 
							
								    positive assertions. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lframe_type  F->temp_32[0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_ASSERT_NOT:
							 | 
						||
| 
								 | 
							
								    case OP_ASSERTBACK_NOT:
							 | 
						||
| 
								 | 
							
								    Lframe_type  = GF_NOCAPTURE | Fop;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (;;)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      group_frame_type = Lframe_type;
							 | 
						||
| 
								 | 
							
								      RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM4);
							 | 
						||
| 
								 | 
							
								      switch(rrc)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        case MATCH_ACCEPT:   /* Assertion matched, therefore it fails. */
							 | 
						||
| 
								 | 
							
								        case MATCH_MATCH:
							 | 
						||
| 
								 | 
							
								        RRETURN (MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case MATCH_NOMATCH:  /* Branch failed, try next if present. */
							 | 
						||
| 
								 | 
							
								        case MATCH_THEN:
							 | 
						||
| 
								 | 
							
								        Fecode += GET(Fecode, 1);
							 | 
						||
| 
								 | 
							
								        if (*Fecode != OP_ALT) goto ASSERT_NOT_FAILED;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        case MATCH_COMMIT:   /* Assertion forced to fail, therefore continue. */
							 | 
						||
| 
								 | 
							
								        case MATCH_SKIP:
							 | 
						||
| 
								 | 
							
								        case MATCH_PRUNE:
							 | 
						||
| 
								 | 
							
								        do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT);
							 | 
						||
| 
								 | 
							
								        goto ASSERT_NOT_FAILED;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        default:             /* Pass back any other return */
							 | 
						||
| 
								 | 
							
								        RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* None of the branches have matched or there was a backtrack to (*COMMIT),
							 | 
						||
| 
								 | 
							
								    (*SKIP), (*PRUNE), or (*THEN) in the last branch. This is success for a
							 | 
						||
| 
								 | 
							
								    negative assertion, so carry on. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ASSERT_NOT_FAILED:
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + LINK_SIZE;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lframe_type
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* The callout item calls an external function, if one is provided, passing
							 | 
						||
| 
								 | 
							
								    details of the match so far. This is mainly for debugging, though the
							 | 
						||
| 
								 | 
							
								    function is able to force a failure. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_CALLOUT:
							 | 
						||
| 
								 | 
							
								    case OP_CALLOUT_STR:
							 | 
						||
| 
								 | 
							
								    rrc = do_callout(F, mb, &length);
							 | 
						||
| 
								 | 
							
								    if (rrc > 0) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    if (rrc < 0) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								    Fecode += length;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Conditional group: compilation checked that there are no more than two
							 | 
						||
| 
								 | 
							
								    branches. If the condition is false, skipping the first branch takes us
							 | 
						||
| 
								 | 
							
								    past the end of the item if there is only one branch, but that's exactly
							 | 
						||
| 
								 | 
							
								    what we want. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_COND:
							 | 
						||
| 
								 | 
							
								    case OP_SCOND:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* The variable Flength will be added to Fecode when the condition is
							 | 
						||
| 
								 | 
							
								    false, to get to the second branch. Setting it to the offset to the ALT or
							 | 
						||
| 
								 | 
							
								    KET, then incrementing Fecode achieves this effect. However, if the second
							 | 
						||
| 
								 | 
							
								    branch is non-existent, we must point to the KET so that the end of the
							 | 
						||
| 
								 | 
							
								    group is correctly processed. We now have Fecode pointing to the condition
							 | 
						||
| 
								 | 
							
								    or callout. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Flength = GET(Fecode, 1);    /* Offset to the second branch */
							 | 
						||
| 
								 | 
							
								    if (Fecode[Flength] != OP_ALT) Flength -= 1 + LINK_SIZE;
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + LINK_SIZE;     /* From this opcode */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Because of the way auto-callout works during compile, a callout item is
							 | 
						||
| 
								 | 
							
								    inserted between OP_COND and an assertion condition. Such a callout can
							 | 
						||
| 
								 | 
							
								    also be inserted manually. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (*Fecode == OP_CALLOUT || *Fecode == OP_CALLOUT_STR)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      rrc = do_callout(F, mb, &length);
							 | 
						||
| 
								 | 
							
								      if (rrc > 0) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      if (rrc < 0) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Advance Fecode past the callout, so it now points to the condition. We
							 | 
						||
| 
								 | 
							
								      must adjust Flength so that the value of Fecode+Flength is unchanged. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Fecode += length;
							 | 
						||
| 
								 | 
							
								      Flength -= length;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Test the various possible conditions */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    condition = FALSE;
							 | 
						||
| 
								 | 
							
								    switch(*Fecode)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      case OP_RREF:                  /* Group recursion test */
							 | 
						||
| 
								 | 
							
								      if (Fcurrent_recurse != RECURSE_UNSET)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        number = GET2(Fecode, 1);
							 | 
						||
| 
								 | 
							
								        condition = (number == RREF_ANY || number == Fcurrent_recurse);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_DNRREF:       /* Duplicate named group recursion test */
							 | 
						||
| 
								 | 
							
								      if (Fcurrent_recurse != RECURSE_UNSET)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        int count = GET2(Fecode, 1 + IMM2_SIZE);
							 | 
						||
| 
								 | 
							
								        PCRE2_SPTR slot = mb->name_table + GET2(Fecode, 1) * mb->name_entry_size;
							 | 
						||
| 
								 | 
							
								        while (count-- > 0)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          number = GET2(slot, 0);
							 | 
						||
| 
								 | 
							
								          condition = number == Fcurrent_recurse;
							 | 
						||
| 
								 | 
							
								          if (condition) break;
							 | 
						||
| 
								 | 
							
								          slot += mb->name_entry_size;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_CREF:                         /* Numbered group used test */
							 | 
						||
| 
								 | 
							
								      offset = (GET2(Fecode, 1) << 1) - 2;  /* Doubled ref number */
							 | 
						||
| 
								 | 
							
								      condition = offset < Foffset_top && Fovector[offset] != PCRE2_UNSET;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_DNCREF:      /* Duplicate named group used test */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        int count = GET2(Fecode, 1 + IMM2_SIZE);
							 | 
						||
| 
								 | 
							
								        PCRE2_SPTR slot = mb->name_table + GET2(Fecode, 1) * mb->name_entry_size;
							 | 
						||
| 
								 | 
							
								        while (count-- > 0)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          offset = (GET2(slot, 0) << 1) - 2;
							 | 
						||
| 
								 | 
							
								          condition = offset < Foffset_top && Fovector[offset] != PCRE2_UNSET;
							 | 
						||
| 
								 | 
							
								          if (condition) break;
							 | 
						||
| 
								 | 
							
								          slot += mb->name_entry_size;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_FALSE:
							 | 
						||
| 
								 | 
							
								      case OP_FAIL:   /* The assertion (?!) becomes OP_FAIL */
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_TRUE:
							 | 
						||
| 
								 | 
							
								      condition = TRUE;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* The condition is an assertion. Run code similar to the assertion code
							 | 
						||
| 
								 | 
							
								      above. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Lpositive      F->temp_32[0]
							 | 
						||
| 
								 | 
							
								#define Lstart_branch  F->temp_sptr[0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      default:
							 | 
						||
| 
								 | 
							
								      Lpositive = (*Fecode == OP_ASSERT || *Fecode == OP_ASSERTBACK);
							 | 
						||
| 
								 | 
							
								      Lstart_branch = Fecode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      for (;;)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        group_frame_type = GF_CONDASSERT | *Fecode;
							 | 
						||
| 
								 | 
							
								        RMATCH(Lstart_branch + PRIV(OP_lengths)[*Lstart_branch], RM5);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        switch(rrc)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          case MATCH_ACCEPT:  /* Save captures */
							 | 
						||
| 
								 | 
							
								          memcpy(Fovector,
							 | 
						||
| 
								 | 
							
								                (char *)assert_accept_frame + offsetof(heapframe, ovector),
							 | 
						||
| 
								 | 
							
								                assert_accept_frame->offset_top * sizeof(PCRE2_SIZE));
							 | 
						||
| 
								 | 
							
								          Foffset_top = assert_accept_frame->offset_top;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* Fall through */
							 | 
						||
| 
								 | 
							
								          /* In the case of a match, the captures have already been put into
							 | 
						||
| 
								 | 
							
								          the current frame. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case MATCH_MATCH:
							 | 
						||
| 
								 | 
							
								          condition = Lpositive;   /* TRUE for positive assertion */
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* PCRE doesn't allow the effect of (*THEN) to escape beyond an
							 | 
						||
| 
								 | 
							
								          assertion; it is therefore always treated as NOMATCH. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case MATCH_NOMATCH:
							 | 
						||
| 
								 | 
							
								          case MATCH_THEN:
							 | 
						||
| 
								 | 
							
								          Lstart_branch += GET(Lstart_branch, 1);
							 | 
						||
| 
								 | 
							
								          if (*Lstart_branch == OP_ALT) continue;  /* Try next branch */
							 | 
						||
| 
								 | 
							
								          condition = !Lpositive;  /* TRUE for negative assertion */
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* These force no match without checking other branches. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          case MATCH_COMMIT:
							 | 
						||
| 
								 | 
							
								          case MATCH_SKIP:
							 | 
						||
| 
								 | 
							
								          case MATCH_PRUNE:
							 | 
						||
| 
								 | 
							
								          condition = !Lpositive;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          default:
							 | 
						||
| 
								 | 
							
								          RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        break;  /* Out of the branch loop */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If the condition is true, find the end of the assertion so that
							 | 
						||
| 
								 | 
							
								      advancing past it gets us to the start of the first branch. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (condition)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      break;  /* End of assertion condition */
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef Lpositive
							 | 
						||
| 
								 | 
							
								#undef Lstart_branch
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Choose branch according to the condition. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Fecode += condition? PRIV(OP_lengths)[*Fecode] : Flength;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If the opcode is OP_SCOND it means we are at a repeated conditional
							 | 
						||
| 
								 | 
							
								    group that might match an empty string. We must therefore descend a level
							 | 
						||
| 
								 | 
							
								    so that the start is remembered for checking. For OP_COND we can just
							 | 
						||
| 
								 | 
							
								    continue at this level. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Fop == OP_SCOND)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      group_frame_type  = GF_NOCAPTURE | Fop;
							 | 
						||
| 
								 | 
							
								      RMATCH(Fecode, RM35);
							 | 
						||
| 
								 | 
							
								      RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ========================================================================= */
							 | 
						||
| 
								 | 
							
								/*                  End of start of parenthesis opcodes                      */
							 | 
						||
| 
								 | 
							
								/* ========================================================================= */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Move the subject pointer back. This occurs only at the start of each
							 | 
						||
| 
								 | 
							
								    branch of a lookbehind assertion. If we are too close to the start to move
							 | 
						||
| 
								 | 
							
								    back, fail. When working with UTF-8 we move back a number of characters,
							 | 
						||
| 
								 | 
							
								    not bytes. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_REVERSE:
							 | 
						||
| 
								 | 
							
								    number = GET(Fecode, 1);
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								    if (utf)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      while (number-- > 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (Feptr <= mb->check_subject) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        Feptr--;
							 | 
						||
| 
								 | 
							
								        BACKCHAR(Feptr);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* No UTF-8 support, or not in UTF-8 mode: count is code unit count */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if ((ptrdiff_t)number > Feptr - mb->start_subject) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      Feptr -= number;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Save the earliest consulted character, then skip to next opcode */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Feptr < mb->start_used_ptr) mb->start_used_ptr = Feptr;
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + LINK_SIZE;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* An alternation is the end of a branch; scan along to find the end of the
							 | 
						||
| 
								 | 
							
								    bracketed group. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_ALT:
							 | 
						||
| 
								 | 
							
								    do Fecode += GET(Fecode,1); while (*Fecode == OP_ALT);
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* The end of a parenthesized group. For all but OP_BRA and OP_COND, the
							 | 
						||
| 
								 | 
							
								    starting frame was added to the chained frames in order to remember the
							 | 
						||
| 
								 | 
							
								    starting subject position for the group. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_KET:
							 | 
						||
| 
								 | 
							
								    case OP_KETRMIN:
							 | 
						||
| 
								 | 
							
								    case OP_KETRMAX:
							 | 
						||
| 
								 | 
							
								    case OP_KETRPOS:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    bracode = Fecode - GET(Fecode, 1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Point N to the frame at the start of the most recent group.
							 | 
						||
| 
								 | 
							
								    Remember the subject pointer at the start of the group. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (*bracode != OP_BRA && *bracode != OP_COND)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      N = (heapframe *)((char *)mb->match_frames + Flast_group_offset);
							 | 
						||
| 
								 | 
							
								      P = (heapframe *)((char *)N - frame_size);
							 | 
						||
| 
								 | 
							
								      Flast_group_offset = P->last_group_offset;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DEBUG_SHOW_RMATCH
							 | 
						||
| 
								 | 
							
								      fprintf(stderr, "++ KET for frame=%d type=%x prev char offset=%lu\n",
							 | 
						||
| 
								 | 
							
								        N->rdepth, N->group_frame_type,
							 | 
						||
| 
								 | 
							
								        (char *)P->eptr - (char *)mb->start_subject);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If we are at the end of an assertion that is a condition, return a
							 | 
						||
| 
								 | 
							
								      match, discarding any intermediate backtracking points. Copy back the
							 | 
						||
| 
								 | 
							
								      mark setting and the captures into the frame before N so that they are
							 | 
						||
| 
								 | 
							
								      set on return. Doing this for all assertions, both positive and negative,
							 | 
						||
| 
								 | 
							
								      seems to match what Perl does. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (GF_IDMASK(N->group_frame_type) == GF_CONDASSERT)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        memcpy((char *)P + offsetof(heapframe, ovector), Fovector,
							 | 
						||
| 
								 | 
							
								          Foffset_top * sizeof(PCRE2_SIZE));
							 | 
						||
| 
								 | 
							
								        P->offset_top = Foffset_top;
							 | 
						||
| 
								 | 
							
								        P->mark = Fmark;
							 | 
						||
| 
								 | 
							
								        Fback_frame = (char *)F - (char *)P;
							 | 
						||
| 
								 | 
							
								        RRETURN(MATCH_MATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else P = NULL;   /* Indicates starting frame not recorded */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* The group was not a conditional assertion. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    switch (*bracode)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      case OP_BRA:    /* No need to do anything for these */
							 | 
						||
| 
								 | 
							
								      case OP_COND:
							 | 
						||
| 
								 | 
							
								      case OP_SCOND:
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Non-atomic positive assertions are like OP_BRA, except that the
							 | 
						||
| 
								 | 
							
								      subject pointer must be put back to where it was at the start of the
							 | 
						||
| 
								 | 
							
								      assertion. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_ASSERT_NA:
							 | 
						||
| 
								 | 
							
								      case OP_ASSERTBACK_NA:
							 | 
						||
| 
								 | 
							
								      if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
							 | 
						||
| 
								 | 
							
								      Feptr = P->eptr;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Atomic positive assertions are like OP_ONCE, except that in addition
							 | 
						||
| 
								 | 
							
								      the subject pointer must be put back to where it was at the start of the
							 | 
						||
| 
								 | 
							
								      assertion. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_ASSERT:
							 | 
						||
| 
								 | 
							
								      case OP_ASSERTBACK:
							 | 
						||
| 
								 | 
							
								      if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
							 | 
						||
| 
								 | 
							
								      Feptr = P->eptr;
							 | 
						||
| 
								 | 
							
								      /* Fall through */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* For an atomic group, discard internal backtracking points. We must
							 | 
						||
| 
								 | 
							
								      also ensure that any remaining branches within the top-level of the group
							 | 
						||
| 
								 | 
							
								      are not tried. Do this by adjusting the code pointer within the backtrack
							 | 
						||
| 
								 | 
							
								      frame so that it points to the final branch. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_ONCE:
							 | 
						||
| 
								 | 
							
								      Fback_frame = ((char *)F - (char *)P);
							 | 
						||
| 
								 | 
							
								      for (;;)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        uint32_t y = GET(P->ecode,1);
							 | 
						||
| 
								 | 
							
								        if ((P->ecode)[y] != OP_ALT) break;
							 | 
						||
| 
								 | 
							
								        P->ecode += y;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* A matching negative assertion returns MATCH, which is turned into
							 | 
						||
| 
								 | 
							
								      NOMATCH at the assertion level. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_ASSERT_NOT:
							 | 
						||
| 
								 | 
							
								      case OP_ASSERTBACK_NOT:
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_MATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* At the end of a script run, apply the script-checking rules. This code
							 | 
						||
| 
								 | 
							
								      will never by exercised if Unicode support it not compiled, because in
							 | 
						||
| 
								 | 
							
								      that environment script runs cause an error at compile time. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_SCRIPT_RUN:
							 | 
						||
| 
								 | 
							
								      if (!PRIV(script_run)(P->eptr, Feptr, utf)) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Whole-pattern recursion is coded as a recurse into group 0, so it
							 | 
						||
| 
								 | 
							
								      won't be picked up here. Instead, we catch it when the OP_END is reached.
							 | 
						||
| 
								 | 
							
								      Other recursion is handled here. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      case OP_CBRA:
							 | 
						||
| 
								 | 
							
								      case OP_CBRAPOS:
							 | 
						||
| 
								 | 
							
								      case OP_SCBRA:
							 | 
						||
| 
								 | 
							
								      case OP_SCBRAPOS:
							 | 
						||
| 
								 | 
							
								      number = GET2(bracode, 1+LINK_SIZE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Handle a recursively called group. We reinstate the previous set of
							 | 
						||
| 
								 | 
							
								      captures and then carry on after the recursion call. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (Fcurrent_recurse == number)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        P = (heapframe *)((char *)N - frame_size);
							 | 
						||
| 
								 | 
							
								        memcpy((char *)F + offsetof(heapframe, ovector), P->ovector,
							 | 
						||
| 
								 | 
							
								          P->offset_top * sizeof(PCRE2_SIZE));
							 | 
						||
| 
								 | 
							
								        Foffset_top = P->offset_top;
							 | 
						||
| 
								 | 
							
								        Fcapture_last = P->capture_last;
							 | 
						||
| 
								 | 
							
								        Fcurrent_recurse = P->current_recurse;
							 | 
						||
| 
								 | 
							
								        Fecode = P->ecode + 1 + LINK_SIZE;
							 | 
						||
| 
								 | 
							
								        continue;  /* With next opcode */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Deal with actual capturing. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      offset = (number << 1) - 2;
							 | 
						||
| 
								 | 
							
								      Fcapture_last = number;
							 | 
						||
| 
								 | 
							
								      Fovector[offset] = P->eptr - mb->start_subject;
							 | 
						||
| 
								 | 
							
								      Fovector[offset+1] = Feptr - mb->start_subject;
							 | 
						||
| 
								 | 
							
								      if (offset >= Foffset_top) Foffset_top = offset + 2;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								      }  /* End actions relating to the starting opcode */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* OP_KETRPOS is a possessive repeating ket. Remember the current position,
							 | 
						||
| 
								 | 
							
								    and return the MATCH_KETRPOS. This makes it possible to do the repeats one
							 | 
						||
| 
								 | 
							
								    at a time from the outer level. This must precede the empty string test -
							 | 
						||
| 
								 | 
							
								    in this case that test is done at the outer level. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (*Fecode == OP_KETRPOS)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      memcpy((char *)P + offsetof(heapframe, eptr),
							 | 
						||
| 
								 | 
							
								             (char *)F + offsetof(heapframe, eptr),
							 | 
						||
| 
								 | 
							
								             frame_copy_size);
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_KETRPOS);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Handle the different kinds of closing brackets. A non-repeating ket
							 | 
						||
| 
								 | 
							
								    needs no special action, just continuing at this level. This also happens
							 | 
						||
| 
								 | 
							
								    for the repeating kets if the group matched no characters, in order to
							 | 
						||
| 
								 | 
							
								    forcibly break infinite loops. Otherwise, the repeating kets try the rest
							 | 
						||
| 
								 | 
							
								    of the pattern or restart from the preceding bracket, in the appropriate
							 | 
						||
| 
								 | 
							
								    order. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Fop != OP_KET && (P == NULL || Feptr != P->eptr))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (Fop == OP_KETRMIN)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        RMATCH(Fecode + 1 + LINK_SIZE, RM6);
							 | 
						||
| 
								 | 
							
								        if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								        Fecode -= GET(Fecode, 1);
							 | 
						||
| 
								 | 
							
								        break;   /* End of ket processing */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* Repeat the maximum number of times (KETRMAX) */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      RMATCH(bracode, RM7);
							 | 
						||
| 
								 | 
							
								      if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Carry on at this level for a non-repeating ket, or after matching an
							 | 
						||
| 
								 | 
							
								    empty string, or after repeating for a maximum number of times. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Fecode += 1 + LINK_SIZE;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Start and end of line assertions, not multiline mode. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_CIRC:   /* Start of line, unless PCRE2_NOTBOL is set. */
							 | 
						||
| 
								 | 
							
								    if (Feptr != mb->start_subject || (mb->moptions & PCRE2_NOTBOL) != 0)
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_SOD:    /* Unconditional start of subject */
							 | 
						||
| 
								 | 
							
								    if (Feptr != mb->start_subject) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* When PCRE2_NOTEOL is unset, assert before the subject end, or a
							 | 
						||
| 
								 | 
							
								    terminating newline unless PCRE2_DOLLAR_ENDONLY is set. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_DOLL:
							 | 
						||
| 
								 | 
							
								    if ((mb->moptions & PCRE2_NOTEOL) != 0) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    if ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0) goto ASSERT_NL_OR_EOS;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Fall through */
							 | 
						||
| 
								 | 
							
								    /* Unconditional end of subject assertion (\z) */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_EOD:
							 | 
						||
| 
								 | 
							
								    if (Feptr < mb->end_subject) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    if (mb->partial != 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								      if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* End of subject or ending \n assertion (\Z) */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_EODN:
							 | 
						||
| 
								 | 
							
								    ASSERT_NL_OR_EOS:
							 | 
						||
| 
								 | 
							
								    if (Feptr < mb->end_subject &&
							 | 
						||
| 
								 | 
							
								        (!IS_NEWLINE(Feptr) || Feptr != mb->end_subject - mb->nllen))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (mb->partial != 0 &&
							 | 
						||
| 
								 | 
							
								          Feptr + 1 >= mb->end_subject &&
							 | 
						||
| 
								 | 
							
								          NLBLOCK->nltype == NLTYPE_FIXED &&
							 | 
						||
| 
								 | 
							
								          NLBLOCK->nllen == 2 &&
							 | 
						||
| 
								 | 
							
								          UCHAR21TEST(Feptr) == NLBLOCK->nl[0])
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								        if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Either at end of string or \n before end. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (mb->partial != 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								      if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Start and end of line assertions, multiline mode. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Start of subject unless notbol, or after any newline except for one at
							 | 
						||
| 
								 | 
							
								    the very end, unless PCRE2_ALT_CIRCUMFLEX is set. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_CIRCM:
							 | 
						||
| 
								 | 
							
								    if ((mb->moptions & PCRE2_NOTBOL) != 0 && Feptr == mb->start_subject)
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    if (Feptr != mb->start_subject &&
							 | 
						||
| 
								 | 
							
								        ((Feptr == mb->end_subject &&
							 | 
						||
| 
								 | 
							
								           (mb->poptions & PCRE2_ALT_CIRCUMFLEX) == 0) ||
							 | 
						||
| 
								 | 
							
								         !WAS_NEWLINE(Feptr)))
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Assert before any newline, or before end of subject unless noteol is
							 | 
						||
| 
								 | 
							
								    set. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_DOLLM:
							 | 
						||
| 
								 | 
							
								    if (Feptr < mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (!IS_NEWLINE(Feptr))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (mb->partial != 0 &&
							 | 
						||
| 
								 | 
							
								            Feptr + 1 >= mb->end_subject &&
							 | 
						||
| 
								 | 
							
								            NLBLOCK->nltype == NLTYPE_FIXED &&
							 | 
						||
| 
								 | 
							
								            NLBLOCK->nllen == 2 &&
							 | 
						||
| 
								 | 
							
								            UCHAR21TEST(Feptr) == NLBLOCK->nl[0])
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          mb->hitend = TRUE;
							 | 
						||
| 
								 | 
							
								          if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if ((mb->moptions & PCRE2_NOTEOL) != 0) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Start of match assertion */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_SOM:
							 | 
						||
| 
								 | 
							
								    if (Feptr != mb->start_subject + mb->start_offset) RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Reset the start of match point */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_SET_SOM:
							 | 
						||
| 
								 | 
							
								    Fstart_match = Feptr;
							 | 
						||
| 
								 | 
							
								    Fecode++;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Word boundary assertions. Find out if the previous and current
							 | 
						||
| 
								 | 
							
								    characters are "word" characters. It takes a bit more work in UTF mode.
							 | 
						||
| 
								 | 
							
								    Characters > 255 are assumed to be "non-word" characters when PCRE2_UCP is
							 | 
						||
| 
								 | 
							
								    not set. When it is set, use Unicode properties if available, even when not
							 | 
						||
| 
								 | 
							
								    in UTF mode. Remember the earliest and latest consulted characters. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_NOT_WORD_BOUNDARY:
							 | 
						||
| 
								 | 
							
								    case OP_WORD_BOUNDARY:
							 | 
						||
| 
								 | 
							
								    if (Feptr == mb->check_subject) prev_is_word = FALSE; else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      PCRE2_SPTR lastptr = Feptr - 1;
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (utf)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        BACKCHAR(lastptr);
							 | 
						||
| 
								 | 
							
								        GETCHAR(fc, lastptr);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								      fc = *lastptr;
							 | 
						||
| 
								 | 
							
								      if (lastptr < mb->start_used_ptr) mb->start_used_ptr = lastptr;
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if ((mb->poptions & PCRE2_UCP) != 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (fc == '_') prev_is_word = TRUE; else
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          int cat = UCD_CATEGORY(fc);
							 | 
						||
| 
								 | 
							
								          prev_is_word = (cat == ucp_L || cat == ucp_N);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								      prev_is_word = CHMAX_255(fc) && (mb->ctypes[fc] & ctype_word) != 0;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Get status of next character */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Feptr >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      SCHECK_PARTIAL();
							 | 
						||
| 
								 | 
							
								      cur_is_word = FALSE;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      PCRE2_SPTR nextptr = Feptr + 1;
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (utf)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        FORWARDCHARTEST(nextptr, mb->end_subject);
							 | 
						||
| 
								 | 
							
								        GETCHAR(fc, Feptr);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								      fc = *Feptr;
							 | 
						||
| 
								 | 
							
								      if (nextptr > mb->last_used_ptr) mb->last_used_ptr = nextptr;
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if ((mb->poptions & PCRE2_UCP) != 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (fc == '_') cur_is_word = TRUE; else
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          int cat = UCD_CATEGORY(fc);
							 | 
						||
| 
								 | 
							
								          cur_is_word = (cat == ucp_L || cat == ucp_N);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								      cur_is_word = CHMAX_255(fc) && (mb->ctypes[fc] & ctype_word) != 0;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Now see if the situation is what we want */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ((*Fecode++ == OP_WORD_BOUNDARY)?
							 | 
						||
| 
								 | 
							
								         cur_is_word == prev_is_word : cur_is_word != prev_is_word)
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* Backtracking (*VERB)s, with and without arguments. Note that if the
							 | 
						||
| 
								 | 
							
								    pattern is successfully matched, we do not come back from RMATCH. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_MARK:
							 | 
						||
| 
								 | 
							
								    Fmark = mb->nomatch_mark = Fecode + 2;
							 | 
						||
| 
								 | 
							
								    RMATCH(Fecode + PRIV(OP_lengths)[*Fecode] + Fecode[1], RM12);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* 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 mb->verb_skip_ptr. If it does match, we
							 | 
						||
| 
								 | 
							
								    return MATCH_SKIP with mb->verb_skip_ptr now pointing to the subject
							 | 
						||
| 
								 | 
							
								    position that corresponds to this mark. Otherwise, pass back the return
							 | 
						||
| 
								 | 
							
								    code unaltered. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (rrc == MATCH_SKIP_ARG &&
							 | 
						||
| 
								 | 
							
								             PRIV(strcmp)(Fecode + 2, mb->verb_skip_ptr) == 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      mb->verb_skip_ptr = Feptr;   /* Pass back current position */
							 | 
						||
| 
								 | 
							
								      RRETURN(MATCH_SKIP);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_FAIL:
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_NOMATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Record the current recursing group number in mb->verb_current_recurse
							 | 
						||
| 
								 | 
							
								    when a backtracking return such as MATCH_COMMIT is given. This enables the
							 | 
						||
| 
								 | 
							
								    recurse processing to catch verbs from within the recursion. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_COMMIT:
							 | 
						||
| 
								 | 
							
								    RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM13);
							 | 
						||
| 
								 | 
							
								    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								    mb->verb_current_recurse = Fcurrent_recurse;
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_COMMIT);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_COMMIT_ARG:
							 | 
						||
| 
								 | 
							
								    Fmark = mb->nomatch_mark = Fecode + 2;
							 | 
						||
| 
								 | 
							
								    RMATCH(Fecode + PRIV(OP_lengths)[*Fecode] + Fecode[1], RM36);
							 | 
						||
| 
								 | 
							
								    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								    mb->verb_current_recurse = Fcurrent_recurse;
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_COMMIT);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_PRUNE:
							 | 
						||
| 
								 | 
							
								    RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM14);
							 | 
						||
| 
								 | 
							
								    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								    mb->verb_current_recurse = Fcurrent_recurse;
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_PRUNE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_PRUNE_ARG:
							 | 
						||
| 
								 | 
							
								    Fmark = mb->nomatch_mark = Fecode + 2;
							 | 
						||
| 
								 | 
							
								    RMATCH(Fecode + PRIV(OP_lengths)[*Fecode] + Fecode[1], RM15);
							 | 
						||
| 
								 | 
							
								    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								    mb->verb_current_recurse = Fcurrent_recurse;
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_PRUNE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_SKIP:
							 | 
						||
| 
								 | 
							
								    RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM16);
							 | 
						||
| 
								 | 
							
								    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								    mb->verb_skip_ptr = Feptr;   /* Pass back current position */
							 | 
						||
| 
								 | 
							
								    mb->verb_current_recurse = Fcurrent_recurse;
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_SKIP);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Note that, for Perl compatibility, SKIP with an argument does NOT set
							 | 
						||
| 
								 | 
							
								    nomatch_mark. When a pattern match ends with a SKIP_ARG for which there was
							 | 
						||
| 
								 | 
							
								    not a matching mark, we have to re-run the match, ignoring the SKIP_ARG
							 | 
						||
| 
								 | 
							
								    that failed and any that precede it (either they also failed, or were not
							 | 
						||
| 
								 | 
							
								    triggered). To do this, we maintain a count of executed SKIP_ARGs. If a
							 | 
						||
| 
								 | 
							
								    SKIP_ARG gets to top level, the match is re-run with mb->ignore_skip_arg
							 | 
						||
| 
								 | 
							
								    set to the count of the one that failed. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_SKIP_ARG:
							 | 
						||
| 
								 | 
							
								    mb->skip_arg_count++;
							 | 
						||
| 
								 | 
							
								    if (mb->skip_arg_count <= mb->ignore_skip_arg)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      Fecode += PRIV(OP_lengths)[*Fecode] + Fecode[1];
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    RMATCH(Fecode + PRIV(OP_lengths)[*Fecode] + Fecode[1], RM17);
							 | 
						||
| 
								 | 
							
								    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Pass back the current skip name and return the special MATCH_SKIP_ARG
							 | 
						||
| 
								 | 
							
								    return code. This will either be caught by a matching MARK, or get to the
							 | 
						||
| 
								 | 
							
								    top, where it causes a rematch with mb->ignore_skip_arg set to the value of
							 | 
						||
| 
								 | 
							
								    mb->skip_arg_count. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mb->verb_skip_ptr = Fecode + 2;
							 | 
						||
| 
								 | 
							
								    mb->verb_current_recurse = Fcurrent_recurse;
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_SKIP_ARG);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* For THEN (and THEN_ARG) we pass back the address of the opcode, so that
							 | 
						||
| 
								 | 
							
								    the branch in which it occurs can be determined. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_THEN:
							 | 
						||
| 
								 | 
							
								    RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM18);
							 | 
						||
| 
								 | 
							
								    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								    mb->verb_ecode_ptr = Fecode;
							 | 
						||
| 
								 | 
							
								    mb->verb_current_recurse = Fcurrent_recurse;
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_THEN);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case OP_THEN_ARG:
							 | 
						||
| 
								 | 
							
								    Fmark = mb->nomatch_mark = Fecode + 2;
							 | 
						||
| 
								 | 
							
								    RMATCH(Fecode + PRIV(OP_lengths)[*Fecode] + Fecode[1], RM19);
							 | 
						||
| 
								 | 
							
								    if (rrc != MATCH_NOMATCH) RRETURN(rrc);
							 | 
						||
| 
								 | 
							
								    mb->verb_ecode_ptr = Fecode;
							 | 
						||
| 
								 | 
							
								    mb->verb_current_recurse = Fcurrent_recurse;
							 | 
						||
| 
								 | 
							
								    RRETURN(MATCH_THEN);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* ===================================================================== */
							 | 
						||
| 
								 | 
							
								    /* There's been some horrible disaster. Arrival here can only mean there is
							 | 
						||
| 
								 | 
							
								    something seriously wrong in the code above or the OP_xxx definitions. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								    return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Do not insert any code in here without much thought; it is assumed
							 | 
						||
| 
								 | 
							
								  that "continue" in the code above comes out to here to repeat the main
							 | 
						||
| 
								 | 
							
								  loop. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  }  /* End of main loop */
							 | 
						||
| 
								 | 
							
								/* Control never reaches here */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ========================================================================= */
							 | 
						||
| 
								 | 
							
								/* The RRETURN() macro jumps here. The number that is saved in Freturn_id
							 | 
						||
| 
								 | 
							
								indicates which label we actually want to return to. The value in Frdepth is
							 | 
						||
| 
								 | 
							
								the index number of the frame in the vector. The return value has been placed
							 | 
						||
| 
								 | 
							
								in rrc. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define LBL(val) case val: goto L_RM##val;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								RETURN_SWITCH:
							 | 
						||
| 
								 | 
							
								if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
							 | 
						||
| 
								 | 
							
								if (Frdepth == 0) return rrc;                     /* Exit from the top level */
							 | 
						||
| 
								 | 
							
								F = (heapframe *)((char *)F - Fback_frame);       /* Backtrack */
							 | 
						||
| 
								 | 
							
								mb->cb->callout_flags |= PCRE2_CALLOUT_BACKTRACK; /* Note for callouts */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef DEBUG_SHOW_RMATCH
							 | 
						||
| 
								 | 
							
								fprintf(stderr, "++ RETURN %d to %d\n", rrc, Freturn_id);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								switch (Freturn_id)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  LBL( 1) LBL( 2) LBL( 3) LBL( 4) LBL( 5) LBL( 6) LBL( 7) LBL( 8)
							 | 
						||
| 
								 | 
							
								  LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(16)
							 | 
						||
| 
								 | 
							
								  LBL(17) LBL(18) LBL(19) LBL(20) LBL(21) LBL(22) LBL(23) LBL(24)
							 | 
						||
| 
								 | 
							
								  LBL(25) LBL(26) LBL(27) LBL(28) LBL(29) LBL(30) LBL(31) LBL(32)
							 | 
						||
| 
								 | 
							
								  LBL(33) LBL(34) LBL(35) LBL(36)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_WIDE_CHARS
							 | 
						||
| 
								 | 
							
								  LBL(100) LBL(101)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								  LBL(200) LBL(201) LBL(202) LBL(203) LBL(204) LBL(205) LBL(206)
							 | 
						||
| 
								 | 
							
								  LBL(207) LBL(208) LBL(209) LBL(210) LBL(211) LBL(212) LBL(213)
							 | 
						||
| 
								 | 
							
								  LBL(214) LBL(215) LBL(216) LBL(217) LBL(218) LBL(219) LBL(220)
							 | 
						||
| 
								 | 
							
								  LBL(221) LBL(222) LBL(223) LBL(224) LBL(225)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  default:
							 | 
						||
| 
								 | 
							
								  return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								#undef LBL
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*************************************************
							 | 
						||
| 
								 | 
							
								*           Match a Regular Expression           *
							 | 
						||
| 
								 | 
							
								*************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* This function applies a compiled pattern to a subject string and picks out
							 | 
						||
| 
								 | 
							
								portions of the string if it matches. Two elements in the vector are set for
							 | 
						||
| 
								 | 
							
								each substring: the offsets to the start and end of the substring.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Arguments:
							 | 
						||
| 
								 | 
							
								  code            points to the compiled expression
							 | 
						||
| 
								 | 
							
								  subject         points to the subject string
							 | 
						||
| 
								 | 
							
								  length          length of subject string (may contain binary zeros)
							 | 
						||
| 
								 | 
							
								  start_offset    where to start in the subject string
							 | 
						||
| 
								 | 
							
								  options         option bits
							 | 
						||
| 
								 | 
							
								  match_data      points to a match_data block
							 | 
						||
| 
								 | 
							
								  mcontext        points a PCRE2 context
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Returns:          > 0 => success; value is the number of ovector pairs filled
							 | 
						||
| 
								 | 
							
								                  = 0 => success, but ovector is not big enough
							 | 
						||
| 
								 | 
							
								                  = -1 => failed to match (PCRE2_ERROR_NOMATCH)
							 | 
						||
| 
								 | 
							
								                  = -2 => partial match (PCRE2_ERROR_PARTIAL)
							 | 
						||
| 
								 | 
							
								                  < -2 => some kind of unexpected problem
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
							 | 
						||
| 
								 | 
							
								pcre2_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
							 | 
						||
| 
								 | 
							
								  PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,
							 | 
						||
| 
								 | 
							
								  pcre2_match_context *mcontext)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								int rc;
							 | 
						||
| 
								 | 
							
								int was_zero_terminated = 0;
							 | 
						||
| 
								 | 
							
								const uint8_t *start_bits = NULL;
							 | 
						||
| 
								 | 
							
								const pcre2_real_code *re = (const pcre2_real_code *)code;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOL anchored;
							 | 
						||
| 
								 | 
							
								BOOL firstline;
							 | 
						||
| 
								 | 
							
								BOOL has_first_cu = FALSE;
							 | 
						||
| 
								 | 
							
								BOOL has_req_cu = FALSE;
							 | 
						||
| 
								 | 
							
								BOOL startline;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH == 8
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR memchr_found_first_cu;
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR memchr_found_first_cu2;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								PCRE2_UCHAR first_cu = 0;
							 | 
						||
| 
								 | 
							
								PCRE2_UCHAR first_cu2 = 0;
							 | 
						||
| 
								 | 
							
								PCRE2_UCHAR req_cu = 0;
							 | 
						||
| 
								 | 
							
								PCRE2_UCHAR req_cu2 = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR bumpalong_limit;
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR end_subject;
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR true_end_subject;
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR start_match;
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR req_cu_ptr;
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR start_partial;
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR match_partial;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_JIT
							 | 
						||
| 
								 | 
							
								BOOL use_jit;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* This flag is needed even when Unicode is not supported for convenience
							 | 
						||
| 
								 | 
							
								(it is used by the IS_NEWLINE macro). */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOL utf = FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								BOOL ucp = FALSE;
							 | 
						||
| 
								 | 
							
								BOOL allow_invalid;
							 | 
						||
| 
								 | 
							
								uint32_t fragment_options = 0;
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_JIT
							 | 
						||
| 
								 | 
							
								BOOL jit_checked_utf = FALSE;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								PCRE2_SIZE frame_size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* We need to have mb as a pointer to a match block, because the IS_NEWLINE
							 | 
						||
| 
								 | 
							
								macro is used below, and it expects NLBLOCK to be defined as a pointer. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								pcre2_callout_block cb;
							 | 
						||
| 
								 | 
							
								match_block actual_match_block;
							 | 
						||
| 
								 | 
							
								match_block *mb = &actual_match_block;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Allocate an initial vector of backtracking frames on the stack. If this
							 | 
						||
| 
								 | 
							
								proves to be too small, it is replaced by a larger one on the heap. To get a
							 | 
						||
| 
								 | 
							
								vector of the size required that is aligned for pointers, allocate it as a
							 | 
						||
| 
								 | 
							
								vector of pointers. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								PCRE2_SPTR stack_frames_vector[START_FRAMES_SIZE/sizeof(PCRE2_SPTR)]
							 | 
						||
| 
								 | 
							
								    PCRE2_KEEP_UNINITIALIZED;
							 | 
						||
| 
								 | 
							
								mb->stack_frames = (heapframe *)stack_frames_vector;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Recognize NULL, length 0 as an empty string. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (subject == NULL && length == 0) subject = (PCRE2_SPTR)"";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Plausibility checks */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if ((options & ~PUBLIC_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;
							 | 
						||
| 
								 | 
							
								if (code == NULL || subject == NULL || match_data == NULL)
							 | 
						||
| 
								 | 
							
								  return PCRE2_ERROR_NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								start_match = subject + start_offset;
							 | 
						||
| 
								 | 
							
								req_cu_ptr = start_match - 1;
							 | 
						||
| 
								 | 
							
								if (length == PCRE2_ZERO_TERMINATED)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  length = PRIV(strlen)(subject);
							 | 
						||
| 
								 | 
							
								  was_zero_terminated = 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								true_end_subject = end_subject = subject + length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (start_offset > length) return PCRE2_ERROR_BADOFFSET;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Check that the first field in the block is the magic number. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Check the code unit width. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if ((re->flags & PCRE2_MODE_MASK) != PCRE2_CODE_UNIT_WIDTH/8)
							 | 
						||
| 
								 | 
							
								  return PCRE2_ERROR_BADMODE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART are match-time flags in the
							 | 
						||
| 
								 | 
							
								options variable for this function. Users of PCRE2 who are not calling the
							 | 
						||
| 
								 | 
							
								function directly would like to have a way of setting these flags, in the same
							 | 
						||
| 
								 | 
							
								way that they can set pcre2_compile() flags like PCRE2_NO_AUTOPOSSESS with
							 | 
						||
| 
								 | 
							
								constructions like (*NO_AUTOPOSSESS). To enable this, (*NOTEMPTY) and
							 | 
						||
| 
								 | 
							
								(*NOTEMPTY_ATSTART) set bits in the pattern's "flag" function which we now
							 | 
						||
| 
								 | 
							
								transfer to the options for this function. The bits are guaranteed to be
							 | 
						||
| 
								 | 
							
								adjacent, but do not have the same values. This bit of Boolean trickery assumes
							 | 
						||
| 
								 | 
							
								that the match-time bits are not more significant than the flag bits. If by
							 | 
						||
| 
								 | 
							
								accident this is not the case, a compile-time division by zero error will
							 | 
						||
| 
								 | 
							
								occur. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define FF (PCRE2_NOTEMPTY_SET|PCRE2_NE_ATST_SET)
							 | 
						||
| 
								 | 
							
								#define OO (PCRE2_NOTEMPTY|PCRE2_NOTEMPTY_ATSTART)
							 | 
						||
| 
								 | 
							
								options |= (re->flags & FF) / ((FF & (~FF+1)) / (OO & (~OO+1)));
							 | 
						||
| 
								 | 
							
								#undef FF
							 | 
						||
| 
								 | 
							
								#undef OO
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* If the pattern was successfully studied with JIT support, we will run the
							 | 
						||
| 
								 | 
							
								JIT executable instead of the rest of this function. Most options must be set
							 | 
						||
| 
								 | 
							
								at compile time for the JIT code to be usable. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_JIT
							 | 
						||
| 
								 | 
							
								use_jit = (re->executable_jit != NULL &&
							 | 
						||
| 
								 | 
							
								          (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Initialize UTF/UCP parameters. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								utf = (re->overall_options & PCRE2_UTF) != 0;
							 | 
						||
| 
								 | 
							
								allow_invalid = (re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0;
							 | 
						||
| 
								 | 
							
								ucp = (re->overall_options & PCRE2_UCP) != 0;
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Convert the partial matching flags into an integer. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->partial = ((options & PCRE2_PARTIAL_HARD) != 0)? 2 :
							 | 
						||
| 
								 | 
							
								              ((options & PCRE2_PARTIAL_SOFT) != 0)? 1 : 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Partial matching and PCRE2_ENDANCHORED are currently not allowed at the same
							 | 
						||
| 
								 | 
							
								time. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (mb->partial != 0 &&
							 | 
						||
| 
								 | 
							
								   ((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)
							 | 
						||
| 
								 | 
							
								  return PCRE2_ERROR_BADOPTION;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* It is an error to set an offset limit without setting the flag at compile
							 | 
						||
| 
								 | 
							
								time. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (mcontext != NULL && mcontext->offset_limit != PCRE2_UNSET &&
							 | 
						||
| 
								 | 
							
								     (re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)
							 | 
						||
| 
								 | 
							
								  return PCRE2_ERROR_BADOFFSETLIMIT;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* If the match data block was previously used with PCRE2_COPY_MATCHED_SUBJECT,
							 | 
						||
| 
								 | 
							
								free the memory that was obtained. Set the field to NULL for no match cases. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  match_data->memctl.free((void *)match_data->subject,
							 | 
						||
| 
								 | 
							
								    match_data->memctl.memory_data);
							 | 
						||
| 
								 | 
							
								  match_data->flags &= ~PCRE2_MD_COPIED_SUBJECT;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								match_data->subject = NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Zero the error offset in case the first code unit is invalid UTF. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								match_data->startchar = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ============================= JIT matching ============================== */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Prepare for JIT matching. Check a UTF string for validity unless no check is
							 | 
						||
| 
								 | 
							
								requested or invalid UTF can be handled. We check only the portion of the
							 | 
						||
| 
								 | 
							
								subject that might be be inspected during matching - from the offset minus the
							 | 
						||
| 
								 | 
							
								maximum lookbehind to the given length. This saves time when a small part of a
							 | 
						||
| 
								 | 
							
								large subject is being matched by the use of a starting offset. Note that the
							 | 
						||
| 
								 | 
							
								maximum lookbehind is a number of characters, not code units. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_JIT
							 | 
						||
| 
								 | 
							
								if (use_jit)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								  if (utf && (options & PCRE2_NO_UTF_CHECK) == 0 && !allow_invalid)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 32
							 | 
						||
| 
								 | 
							
								    unsigned int i;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* For 8-bit and 16-bit UTF, check that the first code unit is a valid
							 | 
						||
| 
								 | 
							
								    character start. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 32
							 | 
						||
| 
								 | 
							
								    if (start_match < end_subject && NOT_FIRSTCU(*start_match))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (start_offset > 0) return PCRE2_ERROR_BADUTFOFFSET;
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH == 8
							 | 
						||
| 
								 | 
							
								      return PCRE2_ERROR_UTF8_ERR20;  /* Isolated 0x80 byte */
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								      return PCRE2_ERROR_UTF16_ERR3;  /* Isolated low surrogate */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								#endif  /* WIDTH != 32 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Move back by the maximum lookbehind, just in case it happens at the very
							 | 
						||
| 
								 | 
							
								    start of matching. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 32
							 | 
						||
| 
								 | 
							
								    for (i = re->max_lookbehind; i > 0 && start_match > subject; i--)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      start_match--;
							 | 
						||
| 
								 | 
							
								      while (start_match > subject &&
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH == 8
							 | 
						||
| 
								 | 
							
								      (*start_match & 0xc0) == 0x80)
							 | 
						||
| 
								 | 
							
								#else  /* 16-bit */
							 | 
						||
| 
								 | 
							
								      (*start_match & 0xfc00) == 0xdc00)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        start_match--;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								#else  /* PCRE2_CODE_UNIT_WIDTH != 32 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* In the 32-bit library, one code unit equals one character. However,
							 | 
						||
| 
								 | 
							
								    we cannot just subtract the lookbehind and then compare pointers, because
							 | 
						||
| 
								 | 
							
								    a very large lookbehind could create an invalid pointer. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (start_offset >= re->max_lookbehind)
							 | 
						||
| 
								 | 
							
								      start_match -= re->max_lookbehind;
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      start_match = subject;
							 | 
						||
| 
								 | 
							
								#endif  /* PCRE2_CODE_UNIT_WIDTH != 32 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Validate the relevant portion of the subject. Adjust the offset of an
							 | 
						||
| 
								 | 
							
								    invalid code point to be an absolute offset in the whole string. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    match_data->rc = PRIV(valid_utf)(start_match,
							 | 
						||
| 
								 | 
							
								      length - (start_match - subject), &(match_data->startchar));
							 | 
						||
| 
								 | 
							
								    if (match_data->rc != 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      match_data->startchar += start_match - subject;
							 | 
						||
| 
								 | 
							
								      return match_data->rc;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    jit_checked_utf = TRUE;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* If JIT returns BADOPTION, which means that the selected complete or
							 | 
						||
| 
								 | 
							
								  partial matching mode was not compiled, fall through to the interpreter. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  rc = pcre2_jit_match(code, subject, length, start_offset, options,
							 | 
						||
| 
								 | 
							
								    match_data, mcontext);
							 | 
						||
| 
								 | 
							
								  if (rc != PCRE2_ERROR_JIT_BADOPTION)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    if (rc >= 0 && (options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      length = CU2BYTES(length + was_zero_terminated);
							 | 
						||
| 
								 | 
							
								      match_data->subject = match_data->memctl.malloc(length,
							 | 
						||
| 
								 | 
							
								        match_data->memctl.memory_data);
							 | 
						||
| 
								 | 
							
								      if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;
							 | 
						||
| 
								 | 
							
								      memcpy((void *)match_data->subject, subject, length);
							 | 
						||
| 
								 | 
							
								      match_data->flags |= PCRE2_MD_COPIED_SUBJECT;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    return rc;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_JIT */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ========================= End of JIT matching ========================== */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Proceed with non-JIT matching. The default is to allow lookbehinds to the
							 | 
						||
| 
								 | 
							
								start of the subject. A UTF check when there is a non-zero offset may change
							 | 
						||
| 
								 | 
							
								this. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->check_subject = subject;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* If a UTF subject string was not checked for validity in the JIT code above,
							 | 
						||
| 
								 | 
							
								check it here, and handle support for invalid UTF strings. The check above
							 | 
						||
| 
								 | 
							
								happens only when invalid UTF is not supported and PCRE2_NO_CHECK_UTF is unset.
							 | 
						||
| 
								 | 
							
								If we get here in those circumstances, it means the subject string is valid,
							 | 
						||
| 
								 | 
							
								but for some reason JIT matching was not successful. There is no need to check
							 | 
						||
| 
								 | 
							
								the subject again.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								We check only the portion of the subject that might be be inspected during
							 | 
						||
| 
								 | 
							
								matching - from the offset minus the maximum lookbehind to the given length.
							 | 
						||
| 
								 | 
							
								This saves time when a small part of a large subject is being matched by the
							 | 
						||
| 
								 | 
							
								use of a starting offset. Note that the maximum lookbehind is a number of
							 | 
						||
| 
								 | 
							
								characters, not code units.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Note also that support for invalid UTF forces a check, overriding the setting
							 | 
						||
| 
								 | 
							
								of PCRE2_NO_CHECK_UTF. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								if (utf &&
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_JIT
							 | 
						||
| 
								 | 
							
								    !jit_checked_utf &&
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    ((options & PCRE2_NO_UTF_CHECK) == 0 || allow_invalid))
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 32
							 | 
						||
| 
								 | 
							
								  BOOL skipped_bad_start = FALSE;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* For 8-bit and 16-bit UTF, check that the first code unit is a valid
							 | 
						||
| 
								 | 
							
								  character start. If we are handling invalid UTF, just skip over such code
							 | 
						||
| 
								 | 
							
								  units. Otherwise, give an appropriate error. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 32
							 | 
						||
| 
								 | 
							
								  if (allow_invalid)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    while (start_match < end_subject && NOT_FIRSTCU(*start_match))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      start_match++;
							 | 
						||
| 
								 | 
							
								      skipped_bad_start = TRUE;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else if (start_match < end_subject && NOT_FIRSTCU(*start_match))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    if (start_offset > 0) return PCRE2_ERROR_BADUTFOFFSET;
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH == 8
							 | 
						||
| 
								 | 
							
								    return PCRE2_ERROR_UTF8_ERR20;  /* Isolated 0x80 byte */
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    return PCRE2_ERROR_UTF16_ERR3;  /* Isolated low surrogate */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif  /* WIDTH != 32 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* The mb->check_subject field points to the start of UTF checking;
							 | 
						||
| 
								 | 
							
								  lookbehinds can go back no further than this. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mb->check_subject = start_match;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Move back by the maximum lookbehind, just in case it happens at the very
							 | 
						||
| 
								 | 
							
								  start of matching, but don't do this if we skipped bad 8-bit or 16-bit code
							 | 
						||
| 
								 | 
							
								  units above. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 32
							 | 
						||
| 
								 | 
							
								  if (!skipped_bad_start)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    unsigned int i;
							 | 
						||
| 
								 | 
							
								    for (i = re->max_lookbehind; i > 0 && mb->check_subject > subject; i--)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      mb->check_subject--;
							 | 
						||
| 
								 | 
							
								      while (mb->check_subject > subject &&
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH == 8
							 | 
						||
| 
								 | 
							
								      (*mb->check_subject & 0xc0) == 0x80)
							 | 
						||
| 
								 | 
							
								#else  /* 16-bit */
							 | 
						||
| 
								 | 
							
								      (*mb->check_subject & 0xfc00) == 0xdc00)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        mb->check_subject--;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#else  /* PCRE2_CODE_UNIT_WIDTH != 32 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* In the 32-bit library, one code unit equals one character. However,
							 | 
						||
| 
								 | 
							
								  we cannot just subtract the lookbehind and then compare pointers, because
							 | 
						||
| 
								 | 
							
								  a very large lookbehind could create an invalid pointer. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (start_offset >= re->max_lookbehind)
							 | 
						||
| 
								 | 
							
								    mb->check_subject -= re->max_lookbehind;
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    mb->check_subject = subject;
							 | 
						||
| 
								 | 
							
								#endif  /* PCRE2_CODE_UNIT_WIDTH != 32 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Validate the relevant portion of the subject. There's a loop in case we
							 | 
						||
| 
								 | 
							
								  encounter bad UTF in the characters preceding start_match which we are
							 | 
						||
| 
								 | 
							
								  scanning because of a lookbehind. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (;;)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    match_data->rc = PRIV(valid_utf)(mb->check_subject,
							 | 
						||
| 
								 | 
							
								      length - (mb->check_subject - subject), &(match_data->startchar));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (match_data->rc == 0) break;   /* Valid UTF string */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Invalid UTF string. Adjust the offset to be an absolute offset in the
							 | 
						||
| 
								 | 
							
								    whole string. If we are handling invalid UTF strings, set end_subject to
							 | 
						||
| 
								 | 
							
								    stop before the bad code unit, and set the options to "not end of line".
							 | 
						||
| 
								 | 
							
								    Otherwise return the error. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    match_data->startchar += mb->check_subject - subject;
							 | 
						||
| 
								 | 
							
								    if (!allow_invalid || match_data->rc > 0) return match_data->rc;
							 | 
						||
| 
								 | 
							
								    end_subject = subject + match_data->startchar;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If the end precedes start_match, it means there is invalid UTF in the
							 | 
						||
| 
								 | 
							
								    extra code units we reversed over because of a lookbehind. Advance past the
							 | 
						||
| 
								 | 
							
								    first bad code unit, and then skip invalid character starting code units in
							 | 
						||
| 
								 | 
							
								    8-bit and 16-bit modes, and try again with the original end point. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (end_subject < start_match)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      mb->check_subject = end_subject + 1;
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 32
							 | 
						||
| 
								 | 
							
								      while (mb->check_subject < start_match && NOT_FIRSTCU(*mb->check_subject))
							 | 
						||
| 
								 | 
							
								        mb->check_subject++;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								      end_subject = true_end_subject;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Otherwise, set the not end of line option, and do the match. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      fragment_options = PCRE2_NOTEOL;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* A NULL match context means "use a default context", but we take the memory
							 | 
						||
| 
								 | 
							
								control functions from the pattern. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (mcontext == NULL)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  mcontext = (pcre2_match_context *)(&PRIV(default_match_context));
							 | 
						||
| 
								 | 
							
								  mb->memctl = re->memctl;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								else mb->memctl = mcontext->memctl;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								anchored = ((re->overall_options | options) & PCRE2_ANCHORED) != 0;
							 | 
						||
| 
								 | 
							
								firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;
							 | 
						||
| 
								 | 
							
								startline = (re->flags & PCRE2_STARTLINE) != 0;
							 | 
						||
| 
								 | 
							
								bumpalong_limit = (mcontext->offset_limit == PCRE2_UNSET)?
							 | 
						||
| 
								 | 
							
								  true_end_subject : subject + mcontext->offset_limit;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Initialize and set up the fixed fields in the callout block, with a pointer
							 | 
						||
| 
								 | 
							
								in the match block. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->cb = &cb;
							 | 
						||
| 
								 | 
							
								cb.version = 2;
							 | 
						||
| 
								 | 
							
								cb.subject = subject;
							 | 
						||
| 
								 | 
							
								cb.subject_length = (PCRE2_SIZE)(end_subject - subject);
							 | 
						||
| 
								 | 
							
								cb.callout_flags = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Fill in the remaining fields in the match block, except for moptions, which
							 | 
						||
| 
								 | 
							
								gets set later. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->callout = mcontext->callout;
							 | 
						||
| 
								 | 
							
								mb->callout_data = mcontext->callout_data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->start_subject = subject;
							 | 
						||
| 
								 | 
							
								mb->start_offset = start_offset;
							 | 
						||
| 
								 | 
							
								mb->end_subject = end_subject;
							 | 
						||
| 
								 | 
							
								mb->hasthen = (re->flags & PCRE2_HASTHEN) != 0;
							 | 
						||
| 
								 | 
							
								mb->allowemptypartial = (re->max_lookbehind > 0) ||
							 | 
						||
| 
								 | 
							
								    (re->flags & PCRE2_MATCH_EMPTY) != 0;
							 | 
						||
| 
								 | 
							
								mb->poptions = re->overall_options;          /* Pattern options */
							 | 
						||
| 
								 | 
							
								mb->ignore_skip_arg = 0;
							 | 
						||
| 
								 | 
							
								mb->mark = mb->nomatch_mark = NULL;          /* In case never set */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* The name table is needed for finding all the numbers associated with a
							 | 
						||
| 
								 | 
							
								given name, for condition testing. The code follows the name table. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->name_table = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code));
							 | 
						||
| 
								 | 
							
								mb->name_count = re->name_count;
							 | 
						||
| 
								 | 
							
								mb->name_entry_size = re->name_entry_size;
							 | 
						||
| 
								 | 
							
								mb->start_code = mb->name_table + re->name_count * re->name_entry_size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Process the \R and newline settings. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->bsr_convention = re->bsr_convention;
							 | 
						||
| 
								 | 
							
								mb->nltype = NLTYPE_FIXED;
							 | 
						||
| 
								 | 
							
								switch(re->newline_convention)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  case PCRE2_NEWLINE_CR:
							 | 
						||
| 
								 | 
							
								  mb->nllen = 1;
							 | 
						||
| 
								 | 
							
								  mb->nl[0] = CHAR_CR;
							 | 
						||
| 
								 | 
							
								  break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  case PCRE2_NEWLINE_LF:
							 | 
						||
| 
								 | 
							
								  mb->nllen = 1;
							 | 
						||
| 
								 | 
							
								  mb->nl[0] = CHAR_NL;
							 | 
						||
| 
								 | 
							
								  break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  case PCRE2_NEWLINE_NUL:
							 | 
						||
| 
								 | 
							
								  mb->nllen = 1;
							 | 
						||
| 
								 | 
							
								  mb->nl[0] = CHAR_NUL;
							 | 
						||
| 
								 | 
							
								  break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  case PCRE2_NEWLINE_CRLF:
							 | 
						||
| 
								 | 
							
								  mb->nllen = 2;
							 | 
						||
| 
								 | 
							
								  mb->nl[0] = CHAR_CR;
							 | 
						||
| 
								 | 
							
								  mb->nl[1] = CHAR_NL;
							 | 
						||
| 
								 | 
							
								  break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  case PCRE2_NEWLINE_ANY:
							 | 
						||
| 
								 | 
							
								  mb->nltype = NLTYPE_ANY;
							 | 
						||
| 
								 | 
							
								  break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  case PCRE2_NEWLINE_ANYCRLF:
							 | 
						||
| 
								 | 
							
								  mb->nltype = NLTYPE_ANYCRLF;
							 | 
						||
| 
								 | 
							
								  break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  default: return PCRE2_ERROR_INTERNAL;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* The backtracking frames have fixed data at the front, and a PCRE2_SIZE
							 | 
						||
| 
								 | 
							
								vector at the end, whose size depends on the number of capturing parentheses in
							 | 
						||
| 
								 | 
							
								the pattern. It is not used at all if there are no capturing parentheses.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  frame_size             is the total size of each frame
							 | 
						||
| 
								 | 
							
								  mb->frame_vector_size  is the total usable size of the vector (rounded down
							 | 
						||
| 
								 | 
							
								                           to a whole number of frames)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The last of these is changed within the match() function if the frame vector
							 | 
						||
| 
								 | 
							
								has to be expanded. We therefore put it into the match block so that it is
							 | 
						||
| 
								 | 
							
								correct when calling match() more than once for non-anchored patterns.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								We must also pad frame_size for alignment to ensure subsequent frames are as
							 | 
						||
| 
								 | 
							
								aligned as heapframe. Whilst ovector is word-aligned due to being a PCRE2_SIZE
							 | 
						||
| 
								 | 
							
								array, that does not guarantee it is suitably aligned for pointers, as some
							 | 
						||
| 
								 | 
							
								architectures have pointers that are larger than a size_t. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								frame_size = (offsetof(heapframe, ovector) +
							 | 
						||
| 
								 | 
							
								  re->top_bracket * 2 * sizeof(PCRE2_SIZE) + HEAPFRAME_ALIGNMENT - 1) &
							 | 
						||
| 
								 | 
							
								  ~(HEAPFRAME_ALIGNMENT - 1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Limits set in the pattern override the match context only if they are
							 | 
						||
| 
								 | 
							
								smaller. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->heap_limit = (mcontext->heap_limit < re->limit_heap)?
							 | 
						||
| 
								 | 
							
								  mcontext->heap_limit : re->limit_heap;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->match_limit = (mcontext->match_limit < re->limit_match)?
							 | 
						||
| 
								 | 
							
								  mcontext->match_limit : re->limit_match;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->match_limit_depth = (mcontext->depth_limit < re->limit_depth)?
							 | 
						||
| 
								 | 
							
								  mcontext->depth_limit : re->limit_depth;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* If a pattern has very many capturing parentheses, the frame size may be very
							 | 
						||
| 
								 | 
							
								large. Ensure that there are at least 10 available frames by getting an initial
							 | 
						||
| 
								 | 
							
								vector on the heap if necessary, except when the heap limit prevents this. Get
							 | 
						||
| 
								 | 
							
								fewer if possible. (The heap limit is in kibibytes.) */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (frame_size <= START_FRAMES_SIZE/10)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  mb->match_frames = mb->stack_frames;   /* Initial frame vector on the stack */
							 | 
						||
| 
								 | 
							
								  mb->frame_vector_size = ((START_FRAMES_SIZE/frame_size) * frame_size);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  mb->frame_vector_size = frame_size * 10;
							 | 
						||
| 
								 | 
							
								  if ((mb->frame_vector_size / 1024) > mb->heap_limit)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    if (frame_size > mb->heap_limit * 1024) return PCRE2_ERROR_HEAPLIMIT;
							 | 
						||
| 
								 | 
							
								    mb->frame_vector_size = ((mb->heap_limit * 1024)/frame_size) * frame_size;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  mb->match_frames = mb->memctl.malloc(mb->frame_vector_size,
							 | 
						||
| 
								 | 
							
								    mb->memctl.memory_data);
							 | 
						||
| 
								 | 
							
								  if (mb->match_frames == NULL) return PCRE2_ERROR_NOMEMORY;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->match_frames_top =
							 | 
						||
| 
								 | 
							
								  (heapframe *)((char *)mb->match_frames + mb->frame_vector_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Write to the ovector within the first frame to mark every capture unset and
							 | 
						||
| 
								 | 
							
								to avoid uninitialized memory read errors when it is copied to a new frame. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								memset((char *)(mb->match_frames) + offsetof(heapframe, ovector), 0xff,
							 | 
						||
| 
								 | 
							
								  frame_size - offsetof(heapframe, ovector));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Pointers to the individual character tables */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mb->lcc = re->tables + lcc_offset;
							 | 
						||
| 
								 | 
							
								mb->fcc = re->tables + fcc_offset;
							 | 
						||
| 
								 | 
							
								mb->ctypes = re->tables + ctypes_offset;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Set up the first code unit to match, if available. If there's no first code
							 | 
						||
| 
								 | 
							
								unit there may be a bitmap of possible first characters. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if ((re->flags & PCRE2_FIRSTSET) != 0)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  has_first_cu = TRUE;
							 | 
						||
| 
								 | 
							
								  first_cu = first_cu2 = (PCRE2_UCHAR)(re->first_codeunit);
							 | 
						||
| 
								 | 
							
								  if ((re->flags & PCRE2_FIRSTCASELESS) != 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    first_cu2 = TABLE_GET(first_cu, mb->fcc, first_cu);
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH == 8
							 | 
						||
| 
								 | 
							
								    if (first_cu > 127 && ucp && !utf) first_cu2 = UCD_OTHERCASE(first_cu);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    if (first_cu > 127 && (utf || ucp)) first_cu2 = UCD_OTHERCASE(first_cu);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								else
							 | 
						||
| 
								 | 
							
								  if (!startline && (re->flags & PCRE2_FIRSTMAPSET) != 0)
							 | 
						||
| 
								 | 
							
								    start_bits = re->start_bitmap;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* There may also be a "last known required character" set. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if ((re->flags & PCRE2_LASTSET) != 0)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  has_req_cu = TRUE;
							 | 
						||
| 
								 | 
							
								  req_cu = req_cu2 = (PCRE2_UCHAR)(re->last_codeunit);
							 | 
						||
| 
								 | 
							
								  if ((re->flags & PCRE2_LASTCASELESS) != 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    req_cu2 = TABLE_GET(req_cu, mb->fcc, req_cu);
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH == 8
							 | 
						||
| 
								 | 
							
								    if (req_cu > 127 && ucp && !utf) req_cu2 = UCD_OTHERCASE(req_cu);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    if (req_cu > 127 && (utf || ucp)) req_cu2 = UCD_OTHERCASE(req_cu);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ==========================================================================*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Loop for handling unanchored repeated matching attempts; for anchored regexs
							 | 
						||
| 
								 | 
							
								the loop runs just once. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								FRAGMENT_RESTART:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								start_partial = match_partial = NULL;
							 | 
						||
| 
								 | 
							
								mb->hitend = FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH == 8
							 | 
						||
| 
								 | 
							
								memchr_found_first_cu = NULL;
							 | 
						||
| 
								 | 
							
								memchr_found_first_cu2 = NULL;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								for(;;)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  PCRE2_SPTR new_start_match;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* ----------------- Start of match optimizations ---------------- */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* There are some optimizations that avoid running the match if a known
							 | 
						||
| 
								 | 
							
								  starting point is not found, or if a known later code unit is not present.
							 | 
						||
| 
								 | 
							
								  However, there is an option (settable at compile time) that disables these,
							 | 
						||
| 
								 | 
							
								  for testing and for ensuring that all callouts do actually occur. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    /* If firstline is TRUE, the start of the match is constrained to the first
							 | 
						||
| 
								 | 
							
								    line of a multiline string. That is, the match must be before or at the
							 | 
						||
| 
								 | 
							
								    first newline following the start of matching. Temporarily adjust
							 | 
						||
| 
								 | 
							
								    end_subject so that we stop the scans for a first code unit at a newline.
							 | 
						||
| 
								 | 
							
								    If the match fails at the newline, later code breaks the loop. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (firstline)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      PCRE2_SPTR t = start_match;
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								      if (utf)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        while (t < end_subject && !IS_NEWLINE(t))
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          t++;
							 | 
						||
| 
								 | 
							
								          ACROSSCHAR(t < end_subject, t, t++);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								      while (t < end_subject && !IS_NEWLINE(t)) t++;
							 | 
						||
| 
								 | 
							
								      end_subject = t;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Anchored: check the first code unit if one is recorded. This may seem
							 | 
						||
| 
								 | 
							
								    pointless but it can help in detecting a no match case without scanning for
							 | 
						||
| 
								 | 
							
								    the required code unit. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (anchored)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (has_first_cu || start_bits != NULL)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        BOOL ok = start_match < end_subject;
							 | 
						||
| 
								 | 
							
								        if (ok)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          PCRE2_UCHAR c = UCHAR21TEST(start_match);
							 | 
						||
| 
								 | 
							
								          ok = has_first_cu && (c == first_cu || c == first_cu2);
							 | 
						||
| 
								 | 
							
								          if (!ok && start_bits != NULL)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								            if (c > 255) c = 255;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            ok = (start_bits[c/8] & (1u << (c&7))) != 0;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        if (!ok)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          rc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Not anchored. Advance to a unique first code unit if there is one. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      if (has_first_cu)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (first_cu != first_cu2)  /* Caseless */
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          /* In 16-bit and 32_bit modes we have to do our own search, so can
							 | 
						||
| 
								 | 
							
								          look for both cases at once. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								          PCRE2_UCHAR smc;
							 | 
						||
| 
								 | 
							
								          while (start_match < end_subject &&
							 | 
						||
| 
								 | 
							
								                (smc = UCHAR21TEST(start_match)) != first_cu &&
							 | 
						||
| 
								 | 
							
								                 smc != first_cu2)
							 | 
						||
| 
								 | 
							
								            start_match++;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								          /* In 8-bit mode, the use of memchr() gives a big speed up, even
							 | 
						||
| 
								 | 
							
								          though we have to call it twice in order to find the earliest
							 | 
						||
| 
								 | 
							
								          occurrence of the code unit in either of its cases. Caching is used
							 | 
						||
| 
								 | 
							
								          to remember the positions of previously found code units. This can
							 | 
						||
| 
								 | 
							
								          make a huge difference when the strings are very long and only one
							 | 
						||
| 
								 | 
							
								          case is actually present. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          PCRE2_SPTR pp1 = NULL;
							 | 
						||
| 
								 | 
							
								          PCRE2_SPTR pp2 = NULL;
							 | 
						||
| 
								 | 
							
								          PCRE2_SIZE searchlength = end_subject - start_match;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* If we haven't got a previously found position for first_cu, or if
							 | 
						||
| 
								 | 
							
								          the current starting position is later, we need to do a search. If
							 | 
						||
| 
								 | 
							
								          the code unit is not found, set it to the end. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (memchr_found_first_cu == NULL ||
							 | 
						||
| 
								 | 
							
								              start_match > memchr_found_first_cu)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            pp1 = memchr(start_match, first_cu, searchlength);
							 | 
						||
| 
								 | 
							
								            memchr_found_first_cu = (pp1 == NULL)? end_subject : pp1;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* If the start is before a previously found position, use the
							 | 
						||
| 
								 | 
							
								          previous position, or NULL if a previous search failed. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          else pp1 = (memchr_found_first_cu == end_subject)? NULL :
							 | 
						||
| 
								 | 
							
								            memchr_found_first_cu;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* Do the same thing for the other case. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (memchr_found_first_cu2 == NULL ||
							 | 
						||
| 
								 | 
							
								              start_match > memchr_found_first_cu2)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            pp2 = memchr(start_match, first_cu2, searchlength);
							 | 
						||
| 
								 | 
							
								            memchr_found_first_cu2 = (pp2 == NULL)? end_subject : pp2;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          else pp2 = (memchr_found_first_cu2 == end_subject)? NULL :
							 | 
						||
| 
								 | 
							
								            memchr_found_first_cu2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* Set the start to the end of the subject if neither case was found.
							 | 
						||
| 
								 | 
							
								          Otherwise, use the earlier found point. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (pp1 == NULL)
							 | 
						||
| 
								 | 
							
								            start_match = (pp2 == NULL)? end_subject : pp2;
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								            start_match = (pp2 == NULL || pp1 < pp2)? pp1 : pp2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  /* 8-bit handling */
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* The caseful case is much simpler. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								          while (start_match < end_subject && UCHAR21TEST(start_match) !=
							 | 
						||
| 
								 | 
							
								                 first_cu)
							 | 
						||
| 
								 | 
							
								            start_match++;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								          start_match = memchr(start_match, first_cu, end_subject - start_match);
							 | 
						||
| 
								 | 
							
								          if (start_match == NULL) start_match = end_subject;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* If we can't find the required first code unit, having reached the
							 | 
						||
| 
								 | 
							
								        true end of the subject, break the bumpalong loop, to force a match
							 | 
						||
| 
								 | 
							
								        failure, except when doing partial matching, when we let the next cycle
							 | 
						||
| 
								 | 
							
								        run at the end of the subject. To see why, consider the pattern
							 | 
						||
| 
								 | 
							
								        /(?<=abc)def/, which partially matches "abc", even though the string
							 | 
						||
| 
								 | 
							
								        does not contain the starting character "d". If we have not reached the
							 | 
						||
| 
								 | 
							
								        true end of the subject (PCRE2_FIRSTLINE caused end_subject to be
							 | 
						||
| 
								 | 
							
								        temporarily modified) we also let the cycle run, because the matching
							 | 
						||
| 
								 | 
							
								        string is legitimately allowed to start with the first code unit of a
							 | 
						||
| 
								 | 
							
								        newline. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (mb->partial == 0 && start_match >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          rc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If there's no first code unit, advance to just after a linebreak for a
							 | 
						||
| 
								 | 
							
								      multiline match if required. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else if (startline)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        if (start_match > mb->start_subject + start_offset)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								          if (utf)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            while (start_match < end_subject && !WAS_NEWLINE(start_match))
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              start_match++;
							 | 
						||
| 
								 | 
							
								              ACROSSCHAR(start_match < end_subject, start_match, start_match++);
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								          while (start_match < end_subject && !WAS_NEWLINE(start_match))
							 | 
						||
| 
								 | 
							
								            start_match++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* 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 code unit. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (start_match[-1] == CHAR_CR &&
							 | 
						||
| 
								 | 
							
								               (mb->nltype == NLTYPE_ANY || mb->nltype == NLTYPE_ANYCRLF) &&
							 | 
						||
| 
								 | 
							
								               start_match < end_subject &&
							 | 
						||
| 
								 | 
							
								               UCHAR21TEST(start_match) == CHAR_NL)
							 | 
						||
| 
								 | 
							
								            start_match++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If there's no first code unit or a requirement for a multiline line
							 | 
						||
| 
								 | 
							
								      start, advance to a non-unique first code unit if any have been
							 | 
						||
| 
								 | 
							
								      identified. The bitmap contains only 256 bits. When code units are 16 or
							 | 
						||
| 
								 | 
							
								      32 bits wide, all code units greater than 254 set the 255 bit. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      else if (start_bits != NULL)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        while (start_match < end_subject)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          uint32_t c = UCHAR21TEST(start_match);
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								          if (c > 255) c = 255;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								          if ((start_bits[c/8] & (1u << (c&7))) != 0) break;
							 | 
						||
| 
								 | 
							
								          start_match++;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* See comment above in first_cu checking about the next few lines. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (mb->partial == 0 && start_match >= mb->end_subject)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          rc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }   /* End first code unit handling */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Restore fudged end_subject */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    end_subject = mb->end_subject;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* The following two optimizations must be disabled for partial matching. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (mb->partial == 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      PCRE2_SPTR p;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* The minimum matching length is a lower bound; no string of that length
							 | 
						||
| 
								 | 
							
								      may actually match the pattern. Although the value is, strictly, in
							 | 
						||
| 
								 | 
							
								      characters, we treat it as code units to avoid spending too much time in
							 | 
						||
| 
								 | 
							
								      this optimization. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (end_subject - start_match < re->minlength)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        rc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /* If req_cu is set, we know that that code unit must appear in the
							 | 
						||
| 
								 | 
							
								      subject for the (non-partial) match to succeed. If the first code unit is
							 | 
						||
| 
								 | 
							
								      set, req_cu 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 caseful/caseless versions makes it go faster,
							 | 
						||
| 
								 | 
							
								      as does using an autoincrement and backing off on a match. As in the case
							 | 
						||
| 
								 | 
							
								      of the first code unit, using memchr() in the 8-bit library gives a big
							 | 
						||
| 
								 | 
							
								      speed up. Unlike the first_cu check above, we do not need to call
							 | 
						||
| 
								 | 
							
								      memchr() twice in the caseless case because we only need to check for the
							 | 
						||
| 
								 | 
							
								      presence of the character in either case, not find the first occurrence.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      The search can be skipped if the code unit was found later than the
							 | 
						||
| 
								 | 
							
								      current starting point in a previous iteration of the bumpalong loop.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      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
							 | 
						||
| 
								 | 
							
								      anchored 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, but it's worth searching a lot more for
							 | 
						||
| 
								 | 
							
								      unanchored patterns. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      p = start_match + (has_first_cu? 1:0);
							 | 
						||
| 
								 | 
							
								      if (has_req_cu && p > req_cu_ptr)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        PCRE2_SIZE check_length = end_subject - start_match;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (check_length < REQ_CU_MAX ||
							 | 
						||
| 
								 | 
							
								              (!anchored && check_length < REQ_CU_MAX * 1000))
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								          if (req_cu != req_cu2)  /* Caseless */
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								            while (p < end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              uint32_t pp = UCHAR21INCTEST(p);
							 | 
						||
| 
								 | 
							
								              if (pp == req_cu || pp == req_cu2) { p--; break; }
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								#else  /* 8-bit code units */
							 | 
						||
| 
								 | 
							
								            PCRE2_SPTR pp = p;
							 | 
						||
| 
								 | 
							
								            p = memchr(pp, req_cu, end_subject - pp);
							 | 
						||
| 
								 | 
							
								            if (p == NULL)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              p = memchr(pp, req_cu2, end_subject - pp);
							 | 
						||
| 
								 | 
							
								              if (p == NULL) p = end_subject;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* The caseful case */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 8
							 | 
						||
| 
								 | 
							
								            while (p < end_subject)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								              if (UCHAR21INCTEST(p) == req_cu) { p--; break; }
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else  /* 8-bit code units */
							 | 
						||
| 
								 | 
							
								            p = memchr(p, req_cu, end_subject - p);
							 | 
						||
| 
								 | 
							
								            if (p == NULL) p = end_subject;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* If we can't find the required code unit, break the bumpalong loop,
							 | 
						||
| 
								 | 
							
								          forcing a match failure. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (p >= end_subject)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            rc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          /* If we have found the required code unit, save the point where we
							 | 
						||
| 
								 | 
							
								          found it, so that we don't search again next time round the bumpalong
							 | 
						||
| 
								 | 
							
								          loop if the start hasn't yet passed this code unit. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          req_cu_ptr = p;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* ------------ End of start of match optimizations ------------ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Give no match if we have passed the bumpalong limit. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (start_match > bumpalong_limit)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    rc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* OK, we can now run the match. If "hitend" is set afterwards, remember the
							 | 
						||
| 
								 | 
							
								  first starting point for which a partial match was found. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  cb.start_match = (PCRE2_SIZE)(start_match - subject);
							 | 
						||
| 
								 | 
							
								  cb.callout_flags |= PCRE2_CALLOUT_STARTMATCH;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mb->start_used_ptr = start_match;
							 | 
						||
| 
								 | 
							
								  mb->last_used_ptr = start_match;
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								  mb->moptions = options | fragment_options;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								  mb->moptions = options;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								  mb->match_call_count = 0;
							 | 
						||
| 
								 | 
							
								  mb->end_offset_top = 0;
							 | 
						||
| 
								 | 
							
								  mb->skip_arg_count = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  rc = match(start_match, mb->start_code, match_data->ovector,
							 | 
						||
| 
								 | 
							
								    match_data->oveccount, re->top_bracket, frame_size, mb);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mb->hitend && start_partial == NULL)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    start_partial = mb->start_used_ptr;
							 | 
						||
| 
								 | 
							
								    match_partial = start_match;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  switch(rc)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    /* If MATCH_SKIP_ARG reaches this level it means that a MARK that matched
							 | 
						||
| 
								 | 
							
								    the SKIP's arg was not found. In this circumstance, Perl ignores the SKIP
							 | 
						||
| 
								 | 
							
								    entirely. The only way we can do that is to re-do the match at the same
							 | 
						||
| 
								 | 
							
								    point, with a flag to force SKIP with an argument to be ignored. Just
							 | 
						||
| 
								 | 
							
								    treating this case as NOMATCH does not work because it does not check other
							 | 
						||
| 
								 | 
							
								    alternatives in patterns such as A(*SKIP:A)B|AC when the subject is AC. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case MATCH_SKIP_ARG:
							 | 
						||
| 
								 | 
							
								    new_start_match = start_match;
							 | 
						||
| 
								 | 
							
								    mb->ignore_skip_arg = mb->skip_arg_count;
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* SKIP passes back the next starting point explicitly, but if it is no
							 | 
						||
| 
								 | 
							
								    greater than the match we have just done, treat it as NOMATCH. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case MATCH_SKIP:
							 | 
						||
| 
								 | 
							
								    if (mb->verb_skip_ptr > start_match)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      new_start_match = mb->verb_skip_ptr;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    /* Fall through */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* NOMATCH and PRUNE advance by one character. THEN at this level acts
							 | 
						||
| 
								 | 
							
								    exactly like PRUNE. Unset ignore SKIP-with-argument. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case MATCH_NOMATCH:
							 | 
						||
| 
								 | 
							
								    case MATCH_PRUNE:
							 | 
						||
| 
								 | 
							
								    case MATCH_THEN:
							 | 
						||
| 
								 | 
							
								    mb->ignore_skip_arg = 0;
							 | 
						||
| 
								 | 
							
								    new_start_match = start_match + 1;
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								    if (utf)
							 | 
						||
| 
								 | 
							
								      ACROSSCHAR(new_start_match < end_subject, new_start_match,
							 | 
						||
| 
								 | 
							
								        new_start_match++);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case MATCH_COMMIT:
							 | 
						||
| 
								 | 
							
								    rc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								    goto ENDLOOP;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Any other return is either a match, or some kind of error. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								    goto ENDLOOP;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Control reaches here for the various types of "no match at this point"
							 | 
						||
| 
								 | 
							
								  result. Reset the code to MATCH_NOMATCH for subsequent checking. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  rc = MATCH_NOMATCH;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* If PCRE2_FIRSTLINE is set, the match must happen before or at the first
							 | 
						||
| 
								 | 
							
								  newline in the subject (though it may continue over the newline). Therefore,
							 | 
						||
| 
								 | 
							
								  if we have just failed to match, starting at a newline, do not continue. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (firstline && IS_NEWLINE(start_match)) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Advance to new matching position */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  start_match = new_start_match;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Break the loop if the pattern is anchored or if we have passed the end of
							 | 
						||
| 
								 | 
							
								  the subject. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (anchored || start_match > end_subject) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* If we have just passed a CR and we are now at a LF, and the pattern does
							 | 
						||
| 
								 | 
							
								  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 code unit. In
							 | 
						||
| 
								 | 
							
								  normal matching start_match will aways be greater than the first position at
							 | 
						||
| 
								 | 
							
								  this stage, but a failed *SKIP can cause a return at the same point, which is
							 | 
						||
| 
								 | 
							
								  why the first test exists. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (start_match > subject + start_offset &&
							 | 
						||
| 
								 | 
							
								      start_match[-1] == CHAR_CR &&
							 | 
						||
| 
								 | 
							
								      start_match < end_subject &&
							 | 
						||
| 
								 | 
							
								      *start_match == CHAR_NL &&
							 | 
						||
| 
								 | 
							
								      (re->flags & PCRE2_HASCRORLF) == 0 &&
							 | 
						||
| 
								 | 
							
								        (mb->nltype == NLTYPE_ANY ||
							 | 
						||
| 
								 | 
							
								         mb->nltype == NLTYPE_ANYCRLF ||
							 | 
						||
| 
								 | 
							
								         mb->nllen == 2))
							 | 
						||
| 
								 | 
							
								    start_match++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mb->mark = NULL;   /* Reset for start of next match attempt */
							 | 
						||
| 
								 | 
							
								  }                  /* End of for(;;) "bumpalong" loop */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ==========================================================================*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* When we reach here, one of the following stopping conditions is true:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(1) The match succeeded, either completely, or partially;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(2) The pattern is anchored or the match was failed after (*COMMIT);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(3) We are past the end of the subject or the bumpalong limit;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(4) PCRE2_FIRSTLINE is set and we have failed to match at a newline, because
							 | 
						||
| 
								 | 
							
								    this option requests that a match occur at or before the first newline in
							 | 
						||
| 
								 | 
							
								    the subject.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(5) Some kind of error occurred.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ENDLOOP:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* If end_subject != true_end_subject, it means we are handling invalid UTF,
							 | 
						||
| 
								 | 
							
								and have just processed a non-terminal fragment. If this resulted in no match
							 | 
						||
| 
								 | 
							
								or a partial match we must carry on to the next fragment (a partial match is
							 | 
						||
| 
								 | 
							
								returned to the caller only at the very end of the subject). A loop is used to
							 | 
						||
| 
								 | 
							
								avoid trying to match against empty fragments; if the pattern can match an
							 | 
						||
| 
								 | 
							
								empty string it would have done so already. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef SUPPORT_UNICODE
							 | 
						||
| 
								 | 
							
								if (utf && end_subject != true_end_subject &&
							 | 
						||
| 
								 | 
							
								    (rc == MATCH_NOMATCH || rc == PCRE2_ERROR_PARTIAL))
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  for (;;)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    /* Advance past the first bad code unit, and then skip invalid character
							 | 
						||
| 
								 | 
							
								    starting code units in 8-bit and 16-bit modes. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    start_match = end_subject + 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if PCRE2_CODE_UNIT_WIDTH != 32
							 | 
						||
| 
								 | 
							
								    while (start_match < true_end_subject && NOT_FIRSTCU(*start_match))
							 | 
						||
| 
								 | 
							
								      start_match++;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* If we have hit the end of the subject, there isn't another non-empty
							 | 
						||
| 
								 | 
							
								    fragment, so give up. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (start_match >= true_end_subject)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      rc = MATCH_NOMATCH;  /* In case it was partial */
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Check the rest of the subject */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mb->check_subject = start_match;
							 | 
						||
| 
								 | 
							
								    rc = PRIV(valid_utf)(start_match, length - (start_match - subject),
							 | 
						||
| 
								 | 
							
								      &(match_data->startchar));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* The rest of the subject is valid UTF. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (rc == 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      mb->end_subject = end_subject = true_end_subject;
							 | 
						||
| 
								 | 
							
								      fragment_options = PCRE2_NOTBOL;
							 | 
						||
| 
								 | 
							
								      goto FRAGMENT_RESTART;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* A subsequent UTF error has been found; if the next fragment is
							 | 
						||
| 
								 | 
							
								    non-empty, set up to process it. Otherwise, let the loop advance. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else if (rc < 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      mb->end_subject = end_subject = start_match + match_data->startchar;
							 | 
						||
| 
								 | 
							
								      if (end_subject > start_match)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        fragment_options = PCRE2_NOTBOL|PCRE2_NOTEOL;
							 | 
						||
| 
								 | 
							
								        goto FRAGMENT_RESTART;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								#endif  /* SUPPORT_UNICODE */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Release an enlarged frame vector that is on the heap. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (mb->match_frames != mb->stack_frames)
							 | 
						||
| 
								 | 
							
								  mb->memctl.free(mb->match_frames, mb->memctl.memory_data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Fill in fields that are always returned in the match data. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								match_data->code = re;
							 | 
						||
| 
								 | 
							
								match_data->mark = mb->mark;
							 | 
						||
| 
								 | 
							
								match_data->matchedby = PCRE2_MATCHEDBY_INTERPRETER;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Handle a fully successful match. Set the return code to the number of
							 | 
						||
| 
								 | 
							
								captured strings, or 0 if there were too many to fit into the ovector, and then
							 | 
						||
| 
								 | 
							
								set the remaining returned values before returning. Make a copy of the subject
							 | 
						||
| 
								 | 
							
								string if requested. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (rc == MATCH_MATCH)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  match_data->rc = ((int)mb->end_offset_top >= 2 * match_data->oveccount)?
							 | 
						||
| 
								 | 
							
								    0 : (int)mb->end_offset_top/2 + 1;
							 | 
						||
| 
								 | 
							
								  match_data->startchar = start_match - subject;
							 | 
						||
| 
								 | 
							
								  match_data->leftchar = mb->start_used_ptr - subject;
							 | 
						||
| 
								 | 
							
								  match_data->rightchar = ((mb->last_used_ptr > mb->end_match_ptr)?
							 | 
						||
| 
								 | 
							
								    mb->last_used_ptr : mb->end_match_ptr) - subject;
							 | 
						||
| 
								 | 
							
								  if ((options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    length = CU2BYTES(length + was_zero_terminated);
							 | 
						||
| 
								 | 
							
								    match_data->subject = match_data->memctl.malloc(length,
							 | 
						||
| 
								 | 
							
								      match_data->memctl.memory_data);
							 | 
						||
| 
								 | 
							
								    if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;
							 | 
						||
| 
								 | 
							
								    memcpy((void *)match_data->subject, subject, length);
							 | 
						||
| 
								 | 
							
								    match_data->flags |= PCRE2_MD_COPIED_SUBJECT;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else match_data->subject = subject;
							 | 
						||
| 
								 | 
							
								  return match_data->rc;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Control gets here if there has been a partial match, an error, or if the
							 | 
						||
| 
								 | 
							
								overall match attempt has failed at all permitted starting positions. Any mark
							 | 
						||
| 
								 | 
							
								data is in the nomatch_mark field. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								match_data->mark = mb->nomatch_mark;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* For anything other than nomatch or partial match, just return the code. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (rc != MATCH_NOMATCH && rc != PCRE2_ERROR_PARTIAL) match_data->rc = rc;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Handle a partial match. If a "soft" partial match was requested, searching
							 | 
						||
| 
								 | 
							
								for a complete match will have continued, and the value of rc at this point
							 | 
						||
| 
								 | 
							
								will be MATCH_NOMATCH. For a "hard" partial match, it will already be
							 | 
						||
| 
								 | 
							
								PCRE2_ERROR_PARTIAL. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								else if (match_partial != NULL)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  match_data->subject = subject;
							 | 
						||
| 
								 | 
							
								  match_data->ovector[0] = match_partial - subject;
							 | 
						||
| 
								 | 
							
								  match_data->ovector[1] = end_subject - subject;
							 | 
						||
| 
								 | 
							
								  match_data->startchar = match_partial - subject;
							 | 
						||
| 
								 | 
							
								  match_data->leftchar = start_partial - subject;
							 | 
						||
| 
								 | 
							
								  match_data->rightchar = end_subject - subject;
							 | 
						||
| 
								 | 
							
								  match_data->rc = PCRE2_ERROR_PARTIAL;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Else this is the classic nomatch case. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								else match_data->rc = PCRE2_ERROR_NOMATCH;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								return match_data->rc;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* End of pcre2_match.c */
							 |