123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332 |
- /*************************************************
- * 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-2021 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_FRAME_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 };
- #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);
- switch(Fecode[1])
- {
- case PT_ANY:
- if (Fop == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
- break;
- case PT_LAMP:
- if ((prop->chartype == ucp_Lu ||
- prop->chartype == ucp_Ll ||
- prop->chartype == ucp_Lt) == (Fop == OP_NOTPROP))
- RRETURN(MATCH_NOMATCH);
- break;
- case PT_GC:
- if ((Fecode[2] != PRIV(ucp_gentype)[prop->chartype]) == (Fop == OP_PROP))
- RRETURN(MATCH_NOMATCH);
- break;
- case PT_PC:
- if ((Fecode[2] != prop->chartype) == (Fop == OP_PROP))
- RRETURN(MATCH_NOMATCH);
- break;
- case PT_SC:
- if ((Fecode[2] != prop->script) == (Fop == OP_PROP))
- 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) == (Fop == OP_NOTPROP))
- 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 (Fop == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
- break;
- default:
- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) ==
- (Fop == OP_NOTPROP)) 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) == (Fop == OP_NOTPROP))
- RRETURN(MATCH_NOMATCH);
- break;
- case PT_CLIST:
- cp = PRIV(ucd_caseless_sets) + Fecode[2];
- for (;;)
- {
- if (fc < *cp)
- { if (Fop == OP_PROP) { RRETURN(MATCH_NOMATCH); } else break; }
- if (fc == *cp++)
- { if (Fop == OP_PROP) break; else { RRETURN(MATCH_NOMATCH); } }
- }
- break;
- case PT_UCNC:
- if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT ||
- fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) ||
- fc >= 0xe000) == (Fop == OP_NOTPROP))
- 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 loop). 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 */
- {
- switch(proptype)
- {
- case PT_ANY:
- if (Lctype == OP_NOTPROP) 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) == (Lctype == OP_NOTPROP))
- 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) == (Lctype == OP_NOTPROP))
- 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) == (Lctype == OP_NOTPROP))
- 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) == (Lctype == OP_NOTPROP))
- 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) == (Lctype == OP_NOTPROP))
- 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 (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
- break;
- default:
- if ((UCD_CATEGORY(fc) == ucp_Z) == (Lctype == OP_NOTPROP))
- 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) == (Lctype == OP_NOTPROP))
- 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 (Lctype == OP_NOTPROP) break;
- RRETURN(MATCH_NOMATCH);
- }
- if (fc == *cp++)
- {
- if (Lctype == OP_NOTPROP) 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) == (Lctype == OP_NOTPROP))
- 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. */
- 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_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 */
- /* 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 loop). */
- else
- {
- Lstart_eptr = Feptr; /* Remember where we started */
- #ifdef SUPPORT_UNICODE
- if (proptype >= 0)
- {
- 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 (Lctype == OP_NOTPROP) 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) == (Lctype == OP_NOTPROP))
- 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) == (Lctype == OP_NOTPROP))
- 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) == (Lctype == OP_NOTPROP))
- 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) == (Lctype == OP_NOTPROP))
- 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) ==
- (Lctype == OP_NOTPROP))
- 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 (Lctype == OP_NOTPROP) goto ENDLOOP99; /* Break the loop */
- break;
- default:
- if ((UCD_CATEGORY(fc) == ucp_Z) == (Lctype == OP_NOTPROP))
- 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) == (Lctype == OP_NOTPROP))
- 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 (Lctype == OP_NOTPROP) break; else goto GOT_MAX; }
- if (fc == *cp++)
- { if (Lctype == OP_NOTPROP) 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) == (Lctype == OP_NOTPROP))
- 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)
- #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 = subject + start_offset;
- PCRE2_SPTR req_cu_ptr = start_match - 1;
- 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;
- /* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated
- subject string. */
- if (length == PCRE2_ZERO_TERMINATED)
- {
- length = PRIV(strlen)(subject);
- was_zero_terminated = 1;
- }
- true_end_subject = end_subject = subject + length;
- /* Plausibility checks */
- if ((options & ~PUBLIC_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;
- if (code == NULL || subject == NULL || match_data == NULL)
- return PCRE2_ERROR_NULL;
- 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. */
- 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
- }
- /* 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. */
- frame_size = offsetof(heapframe, ovector) +
- re->top_bracket * 2 * sizeof(PCRE2_SIZE);
- /* 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,
- re->top_bracket * 2 * sizeof(PCRE2_SIZE));
- /* 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 */
|